aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--envelope.cpp24
-rw-r--r--envelope.h4
-rw-r--r--rsa.cpp55
-rw-r--r--rsa.h19
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;
diff --git a/envelope.h b/envelope.h
index a72a7ad..f7bfad3 100644
--- a/envelope.h
+++ b/envelope.h
@@ -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);
}
diff --git a/rsa.cpp b/rsa.cpp
index e1bf3a8..09ea1bc 100644
--- a/rsa.cpp
+++ b/rsa.cpp
@@ -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;
}
diff --git a/rsa.h b/rsa.h
index f931ab3..bed8400 100644
--- a/rsa.h
+++ b/rsa.h
@@ -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);
}