aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-10-08 11:59:44 +0200
committertomsmeding <tom.smeding@gmail.com>2016-10-08 11:59:44 +0200
commit113f90b689af1d7169df9db5d7e84443972b5f68 (patch)
tree06cea871ae704f5cb335ea2381fa5dd98e9e62d3
parentddeae250bc6661daafb25ae07f8c2e01b53b0d44 (diff)
Add digital envelope encryption
-rw-r--r--envelope.cpp88
-rw-r--r--envelope.h13
-rw-r--r--main.cpp16
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);
+
+}
diff --git a/main.cpp b/main.cpp
index 60198f7..2385da8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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;
}