-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencryption.cs
More file actions
445 lines (425 loc) · 17.2 KB
/
Copy pathencryption.cs
File metadata and controls
445 lines (425 loc) · 17.2 KB
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
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
using System.Security.Cryptography;
using System.IO;
namespace SimplePasswordManager
{
internal class Encryption
{
private const int keySize = 256;
private const int blockSize = 128;
private const int derivationIterations = 100000;
/// <summary>
/// Encrypts a file using AES encryption with the provided password.
/// </summary>
/// <param name="inputFilePath">Path to the input file to encrypt.</param>
/// <param name="outputFilePath">Path where the encrypted file will be saved.</param>
/// <param name="password">Password used for encryption.</param>
/// <exception cref="FileNotFoundException">Thrown if the input file does not exist.</exception>
/// <exception cref="CryptographicException">Thrown if encryption fails.</exception>
/// <exception cref="IOException">Thrown if file operations fail.</exception>
public static void Encrypt(string inputFilePath, string outputFilePath, string password)
{
try
{
if (!File.Exists(inputFilePath))
{
throw new FileNotFoundException("Input file not found.", inputFilePath);
}
byte[] fileBytes = File.ReadAllBytes(inputFilePath);
byte[] salt = GenerateRandomSalt();
byte[] iv = GenerateRandomIV();
byte[] key = DeriveKey(password, salt);
using (Aes aes = Aes.Create())
{
aes.KeySize = keySize;
aes.BlockSize = blockSize;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
using (var outputStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write))
{
outputStream.Write(salt, 0, salt.Length);
outputStream.Write(iv, 0, iv.Length);
using (var cryptoStream = new CryptoStream(outputStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(fileBytes, 0, fileBytes.Length);
cryptoStream.FlushFinalBlock();
}
}
}
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Encrypted file from {inputFilePath} to {outputFilePath}");
}
}
catch (FileNotFoundException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] FileNotFound in Encrypt: {ex.Message}");
}
throw;
}
catch (IOException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] IOException in Encrypt: {ex.Message}");
}
throw;
}
catch (CryptographicException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] CryptographicException in Encrypt: {ex.Message}");
}
throw;
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Unexpected error in Encrypt: {ex.Message}");
}
throw;
}
}
/// <summary>
/// Decrypts a file using AES decryption with the provided password.
/// </summary>
/// <param name="inputFilePath">Path to the encrypted input file.</param>
/// <param name="outputFilePath">Path where the decrypted file will be saved.</param>
/// <param name="password">Password used for decryption.</param>
/// <exception cref="FileNotFoundException">Thrown if the input file does not exist.</exception>
/// <exception cref="CryptographicException">Thrown if decryption fails (e.g., wrong password).</exception>
/// <exception cref="IOException">Thrown if file operations fail.</exception>
public static void Decrypt(string inputFilePath, string outputFilePath, string password)
{
try
{
if (!File.Exists(inputFilePath))
{
throw new FileNotFoundException("Input file not found.", inputFilePath);
}
using (var inputStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read))
{
byte[] salt = new byte[16];
byte[] iv = new byte[16];
inputStream.Read(salt, 0, salt.Length);
inputStream.Read(iv, 0, iv.Length);
byte[] key = DeriveKey(password, salt);
using (Aes aes = Aes.Create())
{
aes.KeySize = keySize;
aes.BlockSize = blockSize;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
using (var outputStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write))
{
using (var cryptoStream = new CryptoStream(outputStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
inputStream.CopyTo(cryptoStream);
cryptoStream.FlushFinalBlock();
}
}
}
}
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Decrypted file from {inputFilePath} to {outputFilePath}");
}
}
catch (FileNotFoundException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] FileNotFound in Decrypt: {ex.Message}");
}
throw;
}
catch (IOException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] IOException in Decrypt: {ex.Message}");
}
throw;
}
catch (CryptographicException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] CryptographicException in Decrypt: {ex.Message}");
}
throw new CryptographicException("AES decryption failed; incorrect password or corrupted data.", ex);
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Unexpected error in Decrypt: {ex.Message}");
}
throw;
}
}
/// <summary>
/// Encrypts a string and saves it to a file.
/// </summary>
/// <param name="encryptionPassword">Password used for encryption.</param>
/// <param name="encryptableString">String to encrypt.</param>
/// <param name="locationToSave">Path where the encrypted file will be saved.</param>
/// <param name="fileName">Name of the temporary file.</param>
/// <exception cref="UnauthorizedAccessException">Thrown if access to the directory is denied.</exception>
/// <exception cref="IOException">Thrown if file operations fail.</exception>
public static void EncryptString(string encryptionPassword, string encryptableString, string locationToSave, string fileName)
{
string tempFolder = Path.Combine(Globals.rootFolder, $"temp_{Guid.NewGuid().ToString()}");
string tempFile = Path.Combine(tempFolder, fileName);
try
{
Directory.CreateDirectory(tempFolder);
File.WriteAllText(tempFile, encryptableString);
Encrypt(tempFile, locationToSave, encryptionPassword);
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] String encrypted and saved to {locationToSave}");
}
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"Error: Access denied to {tempFolder}. Please ensure the application has permission to write to this directory.");
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] UnauthorizedAccess in EncryptString: {ex.Message}");
}
throw;
}
catch (IOException ex)
{
Console.WriteLine($"Error: Failed to create or write to temporary file at {tempFolder}. {ex.Message}");
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] IOException in EncryptString: {ex.Message}");
}
throw;
}
finally
{
try
{
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
if (Directory.Exists(tempFolder))
{
Directory.Delete(tempFolder);
}
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Cleaned up temporary directory {tempFolder}");
}
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Failed to clean up temporary directory {tempFolder}: {ex.Message}");
}
}
}
}
/// <summary>
/// Decrypts a file and returns the decrypted string.
/// </summary>
/// <param name="encryptionPassword">Password used for decryption.</param>
/// <param name="fileToDecrypt">Path to the encrypted file.</param>
/// <returns>The decrypted string.</returns>
/// <exception cref="UnauthorizedAccessException">Thrown if access to the directory is denied.</exception>
/// <exception cref="IOException">Thrown if file operations fail.</exception>
/// <exception cref="CryptographicException">Thrown if decryption fails.</exception>
public static string DecryptString(string encryptionPassword, string fileToDecrypt)
{
string tempFolder = Path.Combine(Globals.rootFolder, $"temp_{Guid.NewGuid().ToString()}");
string tempFile = Path.Combine(tempFolder, "temp_file");
try
{
Directory.CreateDirectory(tempFolder);
Decrypt(fileToDecrypt, tempFile, encryptionPassword);
string decryptedString = File.ReadAllText(tempFile);
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Decrypted string from {fileToDecrypt}");
}
return decryptedString;
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"Error: Access denied to {tempFolder}. Please ensure the application has permission to write to this directory.");
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] UnauthorizedAccess in DecryptString: {ex.Message}");
}
throw;
}
catch (IOException ex)
{
Console.WriteLine($"Error: Failed to read or write to temporary file at {tempFolder}. {ex.Message}");
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] IOException in DecryptString: {ex.Message}");
}
throw;
}
catch (CryptographicException ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] CryptographicException in DecryptString: {ex.Message}");
}
throw;
}
finally
{
try
{
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
if (Directory.Exists(tempFolder))
{
Directory.Delete(tempFolder);
}
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Cleaned up temporary directory {tempFolder}");
}
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Failed to clean up temporary directory {tempFolder}: {ex.Message}");
}
}
}
}
/// <summary>
/// Generates a random string of specified length.
/// </summary>
/// <param name="length">Length of the random string.</param>
/// <returns>A random string containing letters, numbers, and special characters.</returns>
public static string GenerateRandomString(int length)
{
try
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
Random random = new Random();
string result = new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Generated random string of length {length}");
}
return result;
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Error in GenerateRandomString: {ex.Message}");
}
throw;
}
}
/// <summary>
/// Generates a random salt for encryption.
/// </summary>
/// <returns>A 16-byte random salt.</returns>
private static byte[] GenerateRandomSalt()
{
try
{
byte[] salt = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
if (Globals.debugMode)
{
Console.WriteLine("[DEBUG] Generated random salt.");
}
return salt;
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Error in GenerateRandomSalt: {ex.Message}");
}
throw;
}
}
/// <summary>
/// Generates a random initialization vector (IV) for encryption.
/// </summary>
/// <returns>A 16-byte random IV.</returns>
private static byte[] GenerateRandomIV()
{
try
{
byte[] iv = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(iv);
}
if (Globals.debugMode)
{
Console.WriteLine("[DEBUG] Generated random IV.");
}
return iv;
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Error in GenerateRandomIV: {ex.Message}");
}
throw;
}
}
/// <summary>
/// Derives an encryption key from a password and salt using PBKDF2.
/// </summary>
/// <param name="password">The password to derive the key from.</param>
/// <param name="salt">The salt used in key derivation.</param>
/// <returns>A derived key of length keySize/8 bytes.</returns>
private static byte[] DeriveKey(string password, byte[] salt)
{
try
{
using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, derivationIterations, HashAlgorithmName.SHA256))
{
byte[] key = pbkdf2.GetBytes(keySize / 8);
if (Globals.debugMode)
{
Console.WriteLine("[DEBUG] Derived encryption key.");
}
return key;
}
}
catch (Exception ex)
{
if (Globals.debugMode)
{
Console.WriteLine($"[DEBUG] Error in DeriveKey: {ex.Message}");
}
throw;
}
}
}
}