-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathucrypt.cpp
400 lines (390 loc) · 10.3 KB
/
ucrypt.cpp
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/*
* File: ucrypt.cpp
*
* Dependencies: AEScrypt, RSAcrypt, hashlib++
*
* Purpose: Provides a user interface for using RSA and AES cryptographical classes
*
* Authors: Connor Spangler
*
* Last modified: 2 DEC 13
*
* License: Creative Commons Attribution-NonCommercial 4.0 International License
*/
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <vector>
#include <hashlib++/hashlibpp.h>
#include "AEScrypt.h"
//#include "RSAcrypt.h"
using namespace std;
void dispHelp();
int throwError(int e);
vector<int> validKey(char * key);
bool genRSAkeys();
bool keyCheck();
// AES and RSA key sizes in bytes
static const unsigned int AES_KEY_SIZE = 16/sizeof(char);
static const unsigned int RSA_KEY_SIZE = 128/sizeof(char);
// RSA key containers
static const char* RSApubKey = new char[RSA_KEY_SIZE];
static const char* RSAprvKey = new char[RSA_KEY_SIZE];
// RSA class
//static RSAcrypt RSA;
int main(int argc, char * argv[])
{
// SHA256 hash wrapper
hashwrapper *hasher = new sha256wrapper();
// Key containers
string hash;
char* tempKey = new char[AES_KEY_SIZE];
char* key = new char[AES_KEY_SIZE];
char* RSAkey = new char[RSA_KEY_SIZE];
const char* encryptedKey = new char[RSA_KEY_SIZE];
// Directory and filename strings
string ddest = "Decrypted/";
string edest = "Encrypted/";
string path;
string keytxt = "Key.txt";
string keyPath(argv[argc-1]);
// Configuration vector
vector<int> config(2,0);
// Booleans for command line parameters
bool nrsa = false, sti = false, dec = false, rsa = false, del = false, dkey = false;
// Ints for dup and optget
int opt = 0, devNull = open("/dev/null", O_WRONLY), stout = dup(1);
// Get command line parameters
while((opt = getopt(argc, argv, "nqhrsdxk")) != EOF)
{
switch(opt)
{
case 'n':
// New RSA keys
nrsa = true;
break;
case 'q':
// Suppress standard output
dup2(devNull, STDOUT_FILENO);
break;
case 'h':
// Display help
dup2(stout, 1);
close(stout);
dispHelp();
return 0;
break;
case 'r':
// RSA encrypt AES key
rsa = true;
break;
case 's':
// Use standard input for data
sti = true;
break;
case 'd':
// AES descrypt data
dec = true;
break;
case 'x':
// Delete infile after encryption/decryption
del = true;
break;
case 'k':
// RSA decrypt AES keyfile
dkey = true;
break;
default:
// Parameter not found
return throwError(-3);
break;
}
}
if((optind == argc) && !(nrsa && !sti && !dec && !rsa && !del && !dkey))
return throwError(-9);
if(sti && (argc - optind > 1))
return throwError(-10);
// Generate new RSA keys
if(nrsa)
if(!genRSAkeys())
return throwError(-7);
// If RSA is being used, get public and private keys
if(dkey || rsa)
{
// Check that the RSA keys exist
if(!keyCheck())
{
// If the AES key doesn't need to be RSA decrypted
if(!dkey)
{
if(!genRSAkeys())
return throwError(-7);
}
// If the keys don't exist then the keyfile can't be decrypted
else
return throwError(-11);
}
char* tempPubKey = new char[RSA_KEY_SIZE];
char* tempPrvKey = new char[RSA_KEY_SIZE];
ifstream RSApubi("RSA/RSAPub.txt"); // Change to xml in implementation
RSApubi.getline(tempPubKey, 256);
ifstream RSAprvi("RSA/RSAPrv.txt"); // Change to xml in implementation
RSAprvi.getline(tempPrvKey, 256);
RSApubKey = tempPubKey;
RSAprvKey = tempPrvKey;
// RSA.setKeys(RSApubKey, RSAprvKey);
RSApubi.close();
RSAprvi.close();
}
// Read AES key from args if it's not going to be RSA decrypted
if(!dkey)
hash = hasher->getHashFromString(keyPath);
// Read AES key from file otherwise
else
{
ifstream keyFile(keyPath);
if(!keyFile.is_open())
{
cerr << keyPath;
return throwError(-1);
}
keyFile.getline(RSAkey, 256);
// tempKey = RSA.decrypt(RSAkey);
string temp(tempKey);
hash = hasher->getHashFromString(temp.c_str());
}
tempKey = (char*)hash.c_str();
// Concetenate hash to 16 bytes
for(unsigned int x = 0; x < AES_KEY_SIZE; x++)
key[x] = tempKey[x];
// Generate configuration vector and analyze
config = validKey(key);
if(config[0])
return config[1];
// Create AEScrypt object for AES encryption
AEScrypt AES(key);
// If standard input is not being used
if(!sti)
{
// Check if no key was provided or if it is the same as the infile name
if(argc-1 == optind)
return throwError(-8);
// Iterate through files and check all are valid
for(int x = optind; x < argc-1; x++)
{
ifstream in(argv[x]);
if(!in.is_open())
{
cerr << argv[x];
return throwError(-1);
}
in.close();
}
// Iterate through files
for(int x = optind; x < argc-1; x++)
{
ifstream in(argv[x]);
ofstream out;
ustring result;
// AES encrypt file stream
if(!dec)
{
path = edest + argv[x];
out.open(path.c_str());
result = AES.encrypt(in);
}
// AES decrypt file stream
else
{
path = ddest + argv[x];
out.open(path.c_str());
result = AES.decrypt(in);
}
for(unsigned int ln = 0; ln < result.length(); ln++)
out << (unsigned char)result.at(ln);
out.close();
// Delete infile
if(del)
if(remove(argv[x]))
throwError(-6);
in.close();
}
}
// Read data from standard input
else
{
string in;
ofstream out;
// Open file stream to Encrypted
path = edest + "stdin.txt";
out.open(path.c_str(), ios::binary);
// Retrieve data via cin
getline(cin, in);
ustring result;
// AES encrypt data
result = AES.encrypt(in);
for(unsigned int ln = 0; ln < result.length(); ln++)
out << (unsigned char)result.at(ln);
out.close();
}
// RSA encrypt AES key
if(rsa)
{
// encryptedKey = RSA.encrypt(key);
ofstream out(keytxt.c_str());
out << encryptedKey;
out.close();
}
return 0;
}
/*
* Function: bool genRSAkeys()
*
* Purpose: Use RSAcrypt object to generate RSA private and public key files
*
* Arguments: None
*
* Returns: A boolean value indicating whether the keys were successfully generated
*/
bool genRSAkeys()
{
// RSA.genKeys();
// RSApubKey = RSA.getPubKey();
// RSAprvKey = RSA.getPrvKey();
ofstream RSApubo("RSA/RSAPub.txt"); // Change to xml in implementation
ofstream RSAprvo("RSA/RSAPrv.txt"); // Change to xml in implementation
if(!RSApubo.is_open() || !RSAprvo.is_open())
return false;
RSApubo << RSApubKey;
RSAprvo << RSAprvKey;
RSApubo.close();
RSAprvo.close();
return true;
}
/*
* Function: bool keyCheck()
*
* Purpose: Check whether the RSA public and private key files exist
*
* Arguments: None
*
* Returns: A boolean value indicating whether the key files were found
*/
bool keyCheck()
{
ifstream pubin("RSA/RSAPub.txt"); // Change to xml in implementation
ifstream prvin("RSA/RSAPrv.txt"); // Change to xml in implementation
if(!pubin.is_open() || !prvin.is_open())
return false;
return true;
}
/*
* Function: bool validKey(char* key)
*
* Purpose: Check whether the key is a filename or not long enough
*
* Arguments: char * key = AES key
*
* Returns: A bool representing whether the key was good
*/
vector<int> validKey(char* key)
{
vector<int> result(2,0);
ifstream in(key);
if(in.is_open())
{
result[0] = 1;
result[1] = throwError(-4);
}
unsigned int x;
for(x = 0;key[x] != 0;x++){}
if(x > AES_KEY_SIZE)
{
result[0] = 1;
result[1] = throwError(-2);
}
return result;
}
/*
* Function: int throwError(int e)
*
* Purpose: Display an error/warning message based upon the error code e
*
* Arguments: int e = error code
*
* Returns: The original error code supplied
*/
int throwError(int e)
{
switch(e)
{
case -1:
cerr << ": File not found or is corrupted." << endl;
break;
case -2:
cerr << "Error: Key length must be <= 16 bytes." << endl;
break;
case -3:
// Option errors handled by getopt
break;
case -4:
cerr << "Error: Key must be provided and can not be the same as file name." << endl;
break;
case -6:
cerr << "Warning: File deletion failed." << endl;
break;
case -7:
cerr << "Error: Failed to create RSA key outfiles, make sure you have directory write permissions." << endl;
break;
case -8:
cerr << "Error: A valid input file must be provided if -s is not used." << endl;
break;
case -9:
cerr << "Error: Too few arguments. Use -h for usage." << endl;
break;
case -10:
cerr << "Error: Too many arguments. Use -h for usage." << endl;
break;
case -11:
cerr << "Error: No RSA keys exist. Key is undecryptable." << endl;
break;
default:
break;
}
return e;
}
/*
* Function: void dispHelp()
*
* Purpose: Display usage information for ucrypt when -h is used
*
* Arguments: None
*
* Returns: Nothing
*/
void dispHelp()
{
cout << endl << "Usage: ucrypt [OPTION] ... [FILE] ... KEY" << endl;
cout << "Encrypt or decrypt FILE or standard input using KEY." << endl;
cout << "ucrypt results are stored in the local 'Encrypted' or 'Decrypted' folder." << endl;
cout << "If standard input is used, FILE will be the desired output file name." << endl;
cout << "RSA key pair will be generated automatically if none exists." << endl;
cout << "The AES key will be stored in 'Encrypted/FILEKey.xml' if -r is used." << endl;
cout << "The RSA key pair will be stored in'RSA/RSAPub' and 'RSA/RSAPrv'." << endl;
cout << "If RSA key decrypt is used, KEY will be a file containing the AES key." << endl;
cout << "Example: AEScrypt -q -e secrets.txt password123" << endl << endl;
cout << "Cryptographical control:" << endl;
cout << " -d Decrypt AES encrypted FILE" << endl;
cout << " -r RSA encrypt AES key from command line" << endl;
cout << " -k RSA decrypt AES key from file" << endl;
cout << " -n Generate new RSA key pair" << endl << endl;
cout << "Output control:" << endl;
cout << " -q Suppress standard output" << endl;
cout << " -s Use standard in for input" << endl;
cout << " -h Print help info" << endl << endl;
cout << "File control:" << endl;
cout << " -x Delete original file after encryption/decryption" << endl << endl;
}