From aa5365666bb17299035a3d857bcce962004bda1e Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Thu, 6 Oct 2016 20:21:16 +0200 Subject: Base64 and import/export keys --- base64.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base64.h | 10 +++++++ main.cpp | 31 ++++++++++++++++++--- rsa.cpp | 65 +++++++++++++++++++++++++++++++++++++++----- rsa.h | 30 ++++++++++++++------- 5 files changed, 208 insertions(+), 19 deletions(-) create mode 100644 base64.cpp create mode 100644 base64.h diff --git a/base64.cpp b/base64.cpp new file mode 100644 index 0000000..80640f2 --- /dev/null +++ b/base64.cpp @@ -0,0 +1,91 @@ +#include "base64.h" + +using namespace std; + +namespace Base64{ + + char alphabet[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + uint8_t revbet[128]={ +#define XX (127) + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX, //0-15 + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX, //16-31 + XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,62,XX,XX,XX,63, //32-47 + 52,53,54,55,56,57,58,59,60,61,XX,XX,XX,XX,XX,XX, //48-63 + XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, //64-79 + 15,16,17,18,19,20,21,22,23,24,25,XX,XX,XX,XX,XX, //80-95 + XX,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, //96-111 + 41,42,43,44,45,46,47,48,49,50,51,XX,XX,XX,XX,XX, //112-127 +#undef XX + }; + + string encode(const string &data){ + int sz=data.size(); + if(sz==0)return {}; + int blocks=sz/3; + string res(4*blocks+4*(sz%3!=0),'\0'); + int x; + for(int i=0;i>=6; + res[4*i+2]=alphabet[x&0x3f]; x>>=6; + res[4*i+1]=alphabet[x&0x3f]; x>>=6; + res[4*i+0]=alphabet[x]; + } + switch(sz%3){ + case 1: + res[4*blocks+0]=alphabet[(unsigned char)data[3*blocks]>>2]; + res[4*blocks+1]=alphabet[((unsigned char)data[3*blocks]&0x3)<<4]; + res[4*blocks+2]='='; + res[4*blocks+3]='='; + break; + + case 2: + res[4*blocks+0]=alphabet[(unsigned char)data[3*blocks]>>2]; + res[4*blocks+1]=alphabet[(((unsigned char)data[3*blocks]&0x3)<<4)|((unsigned char)data[3*blocks+1]>>4)]; + res[4*blocks+2]=alphabet[(((unsigned char)data[3*blocks+1]&0xf)<<2)]; + res[4*blocks+3]='='; + break; + } + return res; + } + + string decode(const string &dataS){ + int szS=dataS.size(); + if(szS==0)return {}; + uint8_t data[szS]; + int sz=0; + for(char c : dataS){ + if(revbet[c&0x7f]!=127)data[sz++]=revbet[c&0x7f]; + } + + int blocks=sz/4; + int endlen; + if(sz%4==0){ + if(data[sz-1]=='='){ + blocks--; + if(data[sz-2]=='=')endlen=1; + else endlen=2; + } else endlen=0; + } else endlen=sz%4-1; + string res(3*blocks+endlen,'\0'); + int x; + for(int i=0;i>=8; + res[3*i+1]=x&0xff; x>>=8; + res[3*i+0]=x; + } + switch(endlen){ + case 1: + res[3*blocks+0]=(data[4*blocks]<<2)|(data[4*blocks+1]>>4); + break; + + case 2: + res[3*blocks+0]=(data[4*blocks]<<2)|(data[4*blocks+1]>>4); + res[3*blocks+1]=(data[4*blocks+1]<<4)|(data[4*blocks+2]>>2); + break; + } + return res; + } + +} diff --git a/base64.h b/base64.h new file mode 100644 index 0000000..d18f819 --- /dev/null +++ b/base64.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace Base64{ + + std::string encode(const std::string&); + std::string decode(const std::string&); + +} diff --git a/main.cpp b/main.cpp index 491e67b..f818c48 100644 --- a/main.cpp +++ b/main.cpp @@ -6,9 +6,11 @@ #include #include #include +#include "base64.h" #include "bigint.h" #include "numalgo.h" #include "primes.h" +#include "rng.h" #include "rsa.h" using namespace std; @@ -128,7 +130,7 @@ void testisqrt(int argc,char **argv){ } void performrsa(){ - PrivateKey privkey; + RSA::PrivateKey privkey; Bigint p(1000000007),q(3000000019U); privkey.pub.mod=3000000040000000133LL; privkey.pub.exp=65537; @@ -139,9 +141,9 @@ void performrsa(){ cout<<"d = "< #include +#include "base64.h" #include "numalgo.h" +#include "primes.h" +#include "rng.h" #include "rsa.h" -Bigint encrypt(const PublicKey &pubkey,Bigint msg){ - assert(msg>1&&msg1&&msg pq=genprimepair(rng,nbits); + PrivateKey key; + key.pub.mod=pq.first*pq.second; + key.pub.exp=65537; + Bigint x; + egcd((pq.first-Bigint::one)*(pq.second-Bigint::one),key.pub.exp,x,key.pexp); + return key; + } + + PrivateKey genkey(int nbits){ + Arc4Rng rng; + return genkey(nbits,rng); + } + + PrivateKey genkey(int nbits,const string &password){ + KeyRng rng(password); + return genkey(nbits,rng); + } + + pair exportkey(const PrivateKey &key){ + string modser=key.pub.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())); + } + + PrivateKey importkey(const string &pub,const string &priv){ + string pubdeser=Base64::decode(pub); + assert(pubdeser.size()>4); + int modlen=(unsigned char)(pubdeser[0])+(unsigned char)(pubdeser[1]<<8)+ + (unsigned char)(pubdeser[2]<<16)+(unsigned char)(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())); + return key; + } -Bigint decrypt(const PrivateKey &privkey,Bigint encr){ - return expmod(encr,privkey.pexp,privkey.pub.mod); } diff --git a/rsa.h b/rsa.h index ec3c349..abedf84 100644 --- a/rsa.h +++ b/rsa.h @@ -1,15 +1,27 @@ #pragma once +#include +#include #include "bigint.h" -struct PublicKey{ - Bigint mod,exp; -}; +namespace RSA{ -struct PrivateKey{ - PublicKey pub; - Bigint pexp; -}; + struct PublicKey{ + Bigint mod,exp; + }; -Bigint encrypt(const PublicKey&,Bigint); -Bigint decrypt(const PrivateKey&,Bigint); + struct PrivateKey{ + PublicKey pub; + Bigint pexp; + }; + + Bigint encrypt(const PublicKey &key,Bigint msg); + Bigint decrypt(const PrivateKey &key,Bigint msg); + + 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::pair exportkey(const PrivateKey&); //returns {pub,priv} + PrivateKey importkey(const std::string &pub,const std::string &priv); + +} -- cgit v1.2.3-70-g09d2