diff options
| -rw-r--r-- | envelope.cpp | 24 | ||||
| -rw-r--r-- | envelope.h | 4 | ||||
| -rw-r--r-- | rsa.cpp | 55 | ||||
| -rw-r--r-- | rsa.h | 19 | 
4 files changed, 49 insertions, 53 deletions
diff --git a/envelope.cpp b/envelope.cpp index 4674121..5270dae 100644 --- a/envelope.cpp +++ b/envelope.cpp @@ -17,24 +17,25 @@ namespace Envelope{  		return true; //fine  	} -	string encrypt(const string &data,const RSA::PublicKey &pubkey){ +	string encrypt(const string &data,const RSA::Key &pubkey){  		const int keylen=8; //256-bit  		CryptoRng crng; -		string key(4*keylen,'\0'); +		string aeskey(4*keylen,'\0');  		do { -			for(int i=0;i<keylen;i++)*(uint32_t*)&key[4*i]=crng.get(); -		} while(!safeKey(key)); -		// cerr<<"decrkey="<<Base64::encode(key)<<endl; +			for(int i=0;i<keylen;i++)*(uint32_t*)&aeskey[4*i]=crng.get(); +		} while(!safeKey(aeskey)); +		// cerr<<"decrkey="<<Base64::encode(aeskey)<<endl; -		string payload(AES::encrypt(data,key,AES::AES_256_CBC)); +		string payload(AES::encrypt(data,aeskey,AES::AES_256_CBC));  		// cerr<<"payload="<<Base64::encode(payload)<<endl;  		Bigint rsadata; -		for(int i=0;i<(int)key.size();i++){ +		for(int i=0;i<(int)aeskey.size();i++){  			if(i!=0)rsadata<<=8; -			rsadata+=(uint8_t)key[i]; +			rsadata+=(uint8_t)aeskey[i];  		}  		// cerr<<"rsadata="<<rsadata<<endl;  		Bigint res(RSA::encrypt(rsadata,pubkey)); +		// cerr<<"rsaencr="<<res<<endl;  		vector<uint8_t> bytes; //bytes in little-endian order  		while(res!=0){ @@ -44,14 +45,14 @@ namespace Envelope{  		// 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]); +		for(int i=bytes.size()-1;i>=0;i--)payload.push_back(bytes[i]); //append in big-endian order  		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){ +	string decrypt(const string &data,const RSA::Key &privkey){  		// cerr<<"=== DECRYPT ==="<<endl;  		if(data.size()<2)throw invalid_argument("Envelope data length invalid");  		int encrkeylen=((uint16_t)(uint8_t)data[data.size()-2]<<8)+(uint8_t)data.back(); @@ -59,7 +60,7 @@ namespace Envelope{  		// cerr<<"encrkeylen="<<encrkeylen<<endl;  		if((int)data.size()<encrkeylen+2)throw invalid_argument("Envelope key format invalid"); -		string encrkey(encrkeylen,'\0'); +		string encrkey(encrkeylen,'\0'); //in big-endian  		for(int i=0;i<encrkeylen;i++){  			encrkey[i]=data[data.size()-2-encrkeylen+i];  		} @@ -70,6 +71,7 @@ namespace Envelope{  			if(i!=0)rsadata<<=8;  			rsadata+=(uint8_t)encrkey[i];  		} +		// cerr<<"rsaencr="<<rsadata<<endl;  		Bigint res(RSA::decrypt(rsadata,privkey));  		// cerr<<"rsadata="<<res<<endl; @@ -5,9 +5,9 @@  namespace Envelope{ -	std::string encrypt(const std::string &data,const RSA::PublicKey &pubkey); +	std::string encrypt(const std::string &data,const RSA::Key &pubkey);  	//throws invalid_argument for an invalid ciphertext (length invalid) -	std::string decrypt(const std::string &data,const RSA::PrivateKey &privkey); +	std::string decrypt(const std::string &data,const RSA::Key &privkey);  } @@ -1,3 +1,4 @@ +#include <algorithm>  #include <cstdint>  #include <cassert>  #include "base64.h" @@ -10,55 +11,51 @@ using namespace std;  namespace RSA{ -	Bigint encrypt(Bigint msg,const PublicKey &pubkey){ +	Bigint encrypt(Bigint msg,const Key &pubkey){  		assert(msg>1&&msg<pubkey.mod);  		return expmod(msg,pubkey.exp,pubkey.mod);  	} -	Bigint decrypt(Bigint encr,const PrivateKey &privkey){ -		return expmod(encr,privkey.pexp,privkey.pub.mod); +	Bigint decrypt(Bigint encr,const Key &privkey){ +		return expmod(encr,privkey.exp,privkey.mod);  	} -	PrivateKey genkey(int nbits,Rng &rng){ +	pair<Key,Key> genkeys(int nbits,Rng &rng){  		pair<Bigint,Bigint> pq=genprimepair(rng,nbits); -		PrivateKey key; -		key.pub.mod=pq.first*pq.second; -		key.pub.exp=65537; +		Key pubkey,privkey; +		pubkey.mod=privkey.mod=pq.first*pq.second; +		pubkey.exp=65537;  		Bigint x; -		egcd((pq.first-Bigint::one)*(pq.second-Bigint::one),key.pub.exp,x,key.pexp); -		return key; +		assert(egcd((pq.first-Bigint::one)*(pq.second-Bigint::one),pubkey.exp,x,privkey.exp)==1); +		return make_pair(pubkey,privkey);  	} -	PrivateKey genkey(int nbits){ +	pair<Key,Key> genkeys(int nbits){  		CryptoRng rng; -		return genkey(nbits,rng); +		return genkeys(nbits,rng);  	} -	PrivateKey genkey(int nbits,const string &password){ +	pair<Key,Key> genkeys(int nbits,const string &password){  		KeyRng rng(password); -		return genkey(nbits,rng); +		return genkeys(nbits,rng);  	} -	pair<string,string> exportkey(const PrivateKey &key){ -		string modser=key.pub.mod.serialiseMantissa(); +	string exportKey(const Key &key){ +		string modser=key.mod.serialiseMantissa();  		int32_t modlen=modser.size();  		string modlenstr{(char)(modlen&0xff),(char)((modlen>>8)&0xff),(char)((modlen>>16)&0xff),(char)((modlen>>24)&0xff)}; -		return make_pair( -			Base64::encode(modlenstr + modser + key.pub.exp.serialiseMantissa()), -			Base64::encode(modlenstr + modser + key.pexp.serialiseMantissa())); +		return Base64::encode(modlenstr + modser + key.exp.serialiseMantissa());  	} -	PrivateKey importkey(const string &pub,const string &priv){ -		string pubdeser=Base64::decode(pub); -		assert(pubdeser.size()>4); -		int modlen=(uint8_t)pubdeser[0]+((uint8_t)pubdeser[1]<<8)+ -		           ((uint8_t)pubdeser[2]<<16)+((uint8_t)pubdeser[3]<<24); -		assert((int)pubdeser.size()-4>modlen); -		PrivateKey key; -		key.pub.mod.deserialiseMantissa(string(pubdeser.begin()+4,pubdeser.begin()+(4+modlen))); -		key.pub.exp.deserialiseMantissa(string(pubdeser.begin()+(4+modlen),pubdeser.end())); -		string privdeser=Base64::decode(priv); -		key.pexp.deserialiseMantissa(string(privdeser.begin()+(4+modlen),privdeser.end())); +	Key importKey(const string &repr){ +		string deser=Base64::decode(repr); +		if(deser.size()<=4)throw invalid_argument("Invalid key string length"); +		int modlen=(uint8_t)deser[0]+((uint8_t)deser[1]<<8)+ +		           ((uint8_t)deser[2]<<16)+((uint8_t)deser[3]<<24); +		if((int)deser.size()-4-modlen<=0)throw invalid_argument("Key string incomplete"); +		Key key; +		key.mod.deserialiseMantissa(string(deser.begin()+4,deser.begin()+(4+modlen))); +		key.exp.deserialiseMantissa(string(deser.begin()+(4+modlen),deser.end()));  		return key;  	} @@ -6,22 +6,19 @@  namespace RSA{ -	struct PublicKey{ +	struct Key{  		Bigint mod,exp;  	}; -	struct PrivateKey{ -		PublicKey pub; -		Bigint pexp; -	}; +	Bigint encrypt(Bigint msg,const Key &key); +	Bigint decrypt(Bigint msg,const Key &key); -	Bigint encrypt(Bigint msg,const PublicKey &key); -	Bigint decrypt(Bigint msg,const PrivateKey &key); +	std::pair<Key,Key> genkeys(int nbits); //nbits is target number of bits of modulus +	std::pair<Key,Key> genkeys(int nbits,const std::string &password); //generates keys seeded by password -	PrivateKey genkey(int nbits); //nbits is target number of bits of modulus -	PrivateKey genkey(int nbits,const std::string &password); //generates key seeded by password +	std::string exportKey(const Key&); -	std::pair<std::string,std::string> exportkey(const PrivateKey&); //returns {pub,priv} -	PrivateKey importkey(const std::string &pub,const std::string &priv); +	//throws invalid_argument if the imported key is of invalid format +	Key importKey(const std::string &repr);  }  | 
