diff options
-rw-r--r-- | envelope.cpp | 88 | ||||
-rw-r--r-- | envelope.h | 13 | ||||
-rw-r--r-- | main.cpp | 16 |
3 files changed, 115 insertions, 2 deletions
diff --git a/envelope.cpp b/envelope.cpp new file mode 100644 index 0000000..a8cd793 --- /dev/null +++ b/envelope.cpp @@ -0,0 +1,88 @@ +#include <cassert> +#include "aes.h" +#include "base64.h" //TODO: remove +#include "envelope.h" +#include "rng.h" + +using namespace std; + +namespace Envelope{ + + bool safeKey(const string &key){ + //checks against keys 0 and 1, because they don't undergo change in RSA + 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::PublicKey &pubkey){ + const int keylen=8; //256-bit + CryptoRng crng; + string key(4*keylen,'\0'); + do { + for(int i=0;i<keylen;i++)*(uint32_t*)&key[4*i]=crng.get(); + } while(!safeKey(key)); + //cerr<<"WARNING: using predetermined envelope key"<<endl; + //key="kaasKAASkaasKAAShalloHALLOhallo!"; + + cerr<<"decrkey="<<Base64::encode(key)<<endl; + + string payload(AES::encrypt(data,key,AES::AES_256_CBC)); + cerr<<"payload="<<Base64::encode(payload)<<endl; + Bigint rsadata; + for(int i=0;i<(int)key.size();i++){ + if(i!=0)rsadata<<=8; + rsadata+=(uint8_t)key[i]; + } + cerr<<"rsadata="<<rsadata<<endl; + // cerr<<"We encrypt:"<<endl<<" "<<rsadata<<endl; + Bigint res(RSA::encrypt(rsadata,pubkey)); + // cerr<<"to:"<<endl<<" "<<res<<endl; + vector<uint8_t> bytes; //bytes in little-endian order + while(res!=0){ + bytes.push_back(res.lowdigits()&0xff); + res>>=8; + } + cerr<<"encrkey="<<Base64::encode(string(bytes.rbegin(),bytes.rend()))<<endl; + payload.reserve(payload.size()+bytes.size()+2); + for(int i=bytes.size()-1;i>=0;i--)payload.push_back(bytes[i]); + payload.push_back(bytes.size()>>8); + payload.push_back((uint8_t)bytes.size()&0xff); + + return payload; + } + + string decrypt(const string &data,const RSA::PrivateKey &privkey){ + cerr<<"=== DECRYPT ==="<<endl; + if(data.size()<2)throw invalid_argument("Envelope data length invalid"); + int encrkeylen=((uint16_t)data[data.size()-2]<<8)+(uint16_t)data.back(); + assert(encrkeylen<(1<<16)); + cerr<<"encrkeylen="<<encrkeylen<<endl; + if((int)data.size()<encrkeylen+2)throw invalid_argument("Envelope key format invalid"); + string encrkey(encrkeylen,'\0'); + for(int i=0;i<encrkeylen;i++){ + encrkey[i]=data[data.size()-2-encrkeylen+i]; + } + cerr<<"encrkey="<<Base64::encode(encrkey)<<endl; + Bigint rsadata; + for(int i=0;i<encrkeylen;i++){ + if(i!=0)rsadata<<=8; + rsadata+=(uint8_t)encrkey[i]; + } + Bigint res(RSA::decrypt(rsadata,privkey)); + cerr<<"rsadata="<<res<<endl; + vector<uint8_t> bytes; //bytes in little-endian order + while(res!=0){ + bytes.push_back(res.lowdigits()&0xff); + res>>=8; + } + string decrkey(bytes.size(),'\0'); + for(int i=0;i<(int)bytes.size();i++)decrkey[bytes.size()-1-i]=bytes[i]; + cerr<<"decrkey="<<Base64::encode(decrkey)<<endl; + cerr<<"payload="<<Base64::encode(data.substr(0,data.size()-2-encrkeylen))<<endl; + return AES::decrypt(data.substr(0,data.size()-2-encrkeylen),decrkey,AES::AES_256_CBC); + } + +} diff --git a/envelope.h b/envelope.h new file mode 100644 index 0000000..a72a7ad --- /dev/null +++ b/envelope.h @@ -0,0 +1,13 @@ +#pragma once + +#include <string> +#include "rsa.h" + +namespace Envelope{ + + std::string encrypt(const std::string &data,const RSA::PublicKey &pubkey); + + //throws invalid_argument for an invalid ciphertext (length invalid) + std::string decrypt(const std::string &data,const RSA::PrivateKey &privkey); + +} @@ -10,6 +10,7 @@ #include "aes.h" #include "base64.h" #include "bigint.h" +#include "envelope.h" #include "numalgo.h" #include "primes.h" #include "rng.h" @@ -223,6 +224,17 @@ int main(int argc,char **argv){ // cout<<Base64::decode(s)<<flush;*/ // AES::test(); - cout<<Base64::encode(AES::encrypt("123456789abcdefx","goeiemorgen dit is leuke data enzoo",AES::AES_128_CBC))<<endl; - cout<<AES::decrypt("123456789abcdefx",Base64::decode("dv2N3n2FHsD7LU2PAZnZm/bLQQSaaZoDDFjy3VrSu2JCHN5KuyBlinlh9C71IGTbT4/WvRKLp6dp1TfrKXIG2w=="),AES::AES_128_CBC)<<endl; + // cout<<Base64::encode(AES::encrypt("goeiemorgen dit is leuke data enzoo","123456789abcdefx",AES::AES_128_CBC))<<endl; + // cout<<AES::decrypt(Base64::decode("dv2N3n2FHsD7LU2PAZnZm/bLQQSaaZoDDFjy3VrSu2JCHN5KuyBlinlh9C71IGTbT4/WvRKLp6dp1TfrKXIG2w=="),"123456789abcdefx",AES::AES_128_CBC)<<endl; + + RSA::PrivateKey privkey(RSA::genkey(2048,"goeiemorgen")); + cerr<<"privkey.pexp="<<privkey.pexp<<endl; + // stringstream ss("146142527763115590918816237475833862275078269531224490080731579415134484175830244922030574137988310092068583287060550616357026989772917226684940867892409"); + // Bigint d; + // ss>>d; + // cout<<RSA::decrypt(d,privkey)<<endl; + string crypt(Envelope::encrypt("hallo hallo dit is leuke data enzo",privkey.pub)); + cout<<Base64::encode(crypt)<<endl; + string decr(Envelope::decrypt(crypt,privkey)); + cout<<decr<<endl; } |