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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include "../base64.h"
#include "../envelope.h"
using namespace std;
const char *progname="envelope";
void usage(){
cerr<<"Usage: " <<endl
<<" "<<progname<<" -k <keylength> Generate a key with the given number of bits" <<endl
<<" "<<progname<<" -e <pubkey> Encrypt text on standard input" <<endl
<<" "<<progname<<" -d <privkey> Decrypt text on standard input" <<endl
<<endl
<<"The program first encrypts the plaintext using 256-bit AES CBC with a randomly" <<endl
<<"generated key, and then encrypts the key using RSA, with the specified key." <<endl
<<"All RSA keys are encoded in base64 in an internal format." <<endl
<<endl
<<"The <keylength> used for RSA key generation is the number of bits in the" <<endl
<<"modulus. Advised for security is at least 2048, but that might take a while to" <<endl
<<"generate (be patient...). (Note: duration of key generation has *absolutely no*" <<endl
<<"meaning as to the strength of the key.) There is no restriction to powers of two"<<endl
<<"in the key length (or any other special class of numbers), but stay above 512," <<endl
<<"or the AES key might not fit." <<endl
<<endl
<<" -k The public and private keys are printed on standard output, separated by" <<endl
<<" newlines. Comments are on standard error." <<endl
<<" -e Text to encrypt is expected on standard input; the public key of the" <<endl
<<" recipient is a command-line argument. Encrypted text is in base64 on" <<endl
<<" standard output." <<endl
<<" -d Text to decrypt is expected on standard input, in the base64 form that is" <<endl
<<" outputted by the -e function. your private key is a command-line argument."<<endl
<<" Decrypted text is on standard output." <<endl;
}
void mode_keygen(int keylength){
if(keylength<512){
cerr<<"Key length too small, please specify length >= 512"<<endl;
exit(1);
}
if(keylength>8192){
cerr<<"Key length too large, please specify length <= 8192"<<endl;
exit(1);
}
pair<RSA::Key,RSA::Key> keyset=RSA::genkeys(keylength);
cerr<<"Public key:"<<endl;
cout<<RSA::exportKey(keyset.first)<<endl;
cerr<<"Private key:"<<endl;
cout<<RSA::exportKey(keyset.second)<<endl;
}
void mode_encrypt(const string &pubkeyrepr){
RSA::Key key;
try {
key=RSA::importKey(pubkeyrepr);
} catch(invalid_argument){
cerr<<"The given public key is not a valid key!"<<endl;
exit(1);
}
string data;
char buf[1024];
while(cin){
cin.read(buf,sizeof(buf));
int nread=cin.gcount();
if(nread==0)continue;
data.append(buf,nread);
}
cout<<Base64::encode(Envelope::encrypt(data,key))<<endl;
}
void mode_decrypt(const string &privkeyrepr){
RSA::Key key;
try {
key=RSA::importKey(privkeyrepr);
} catch(invalid_argument){
cerr<<"The given private key is not a valid key!"<<endl;
exit(1);
}
string data;
char buf[1024];
while(cin){
cin.read(buf,sizeof(buf));
int nread=cin.gcount();
if(nread==0)continue;
data.append(buf,nread);
}
try {
cout<<Envelope::decrypt(Base64::decode(data),key)<<flush;
} catch(invalid_argument){
cerr<<"Private key doesn't match encrypted text!"<<endl;
exit(1);
}
}
int main(int argc,char **argv){
if(argc==3&&strcmp(argv[1],"-k")==0){
char *endp;
int keylength=strtol(argv[2],&endp,10);
if(!argv[2][0]||*endp){
cerr<<"Invalid number '"<<argv[2]<<"'"<<endl;
usage();
return 1;
}
mode_keygen(keylength);
} else if(argc==3&&strcmp(argv[1],"-e")==0){
mode_encrypt(argv[2]);
} else if(argc==3&&strcmp(argv[1],"-d")==0){
mode_decrypt(argv[2]);
} else {
usage();
return 1;
}
}
|