#include #include #include "aes.h" #include "envelope.h" #include "rng.h" #undef DEBUG #ifdef DEBUG #include "base64.h" #endif using namespace std; namespace Envelope{ // Envelope format: [AES encrypted data | RSA encrypted AES key | length of AES key] // The encrypted AES key is in big-endian format, as is the length tag. The length tag // is an unsigned 16-bit integer. bool safeKey(const string &key){ //checks against keys 0 and 1, because they don't undergo change in RSA enryption int i; for(i=0;i<(int)key.size();i++)if(key[i]!=0)break; if(i==(int)key.size())return false; //key is 0 if(i==(int)key.size()-1&&key[i]==1)return false; //key is 1 return true; //fine } string encrypt(const string &data,const RSA::Key &pubkey){ const int keylen=8; //256-bit CryptoRng crng; string aeskey(4*keylen,'\0'); do { for(int i=0;i bytes; //bytes in little-endian order (so, reversed!) while(res!=0){ bytes.push_back(res.lowdigits()&0xff); res>>=8; } payload.reserve(payload.size()+bytes.size()+2); for(int i=bytes.size()-1;i>=0;i--)payload.push_back(bytes[i]); //append in big-endian order again payload.push_back(bytes.size()>>8); payload.push_back((uint8_t)bytes.size()&0xff); return payload; } string decrypt(const string &data,const RSA::Key &privkey){ if(data.size()<2)throw invalid_argument("Envelope data length invalid"); //This double cast is necessary because of sign extension. int encrkeylen=((uint16_t)(uint8_t)data[data.size()-2]<<8)+(uint8_t)data.back(); assert(encrkeylen<(1<<16)); if((int)data.size() bytes; //bytes in little-endian order for(int i=0;i<32;i++){ //32 is the number of bytes in a 256-bit AES key (256/8=32) bytes.push_back(res.lowdigits()&0xff); res>>=8; } if(res!=0){ throw invalid_argument("Envelope RSA private key incorrect"); } string decrkey(bytes.size(),'\0'); for(int i=0;i<(int)bytes.size();i++)decrkey[bytes.size()-1-i]=bytes[i]; //save in decrkey in big-endian order again try { return AES::decrypt(data.substr(0,data.size()-2-encrkeylen),decrkey,AES::AES_256_CBC); } catch(invalid_argument){ throw invalid_argument("Envelope RSA private key incorrect"); } } }