aboutsummaryrefslogtreecommitdiff
path: root/rsa.cpp
blob: b6ad5ed4c3745daa208e34678630d14047ef63df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <cstdint>
#include <cassert>
#include "base64.h"
#include "numalgo.h"
#include "primes.h"
#include "rng.h"
#include "rsa.h"

using namespace std;

namespace RSA{

	Bigint encrypt(const PublicKey &pubkey,Bigint msg){
		assert(msg>1&&msg<pubkey.mod);
		return expmod(msg,pubkey.exp,pubkey.mod);
	}

	Bigint decrypt(const PrivateKey &privkey,Bigint encr){
		return expmod(encr,privkey.pexp,privkey.pub.mod);
	}

	PrivateKey genkey(int nbits,Rng &rng){
		pair<Bigint,Bigint> 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){
		CryptoRng rng;
		return genkey(nbits,rng);
	}

	PrivateKey genkey(int nbits,const string &password){
		KeyRng rng(password);
		return genkey(nbits,rng);
	}

	pair<string,string> 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;
	}

}