|
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+using System;
|
|
|
2
|
+using System.IO;
|
|
|
3
|
+using System.Security.Cryptography;
|
|
|
4
|
+
|
|
|
5
|
+namespace WpfApplication19
|
|
|
6
|
+{
|
|
|
7
|
+ //
|
|
|
8
|
+
|
|
|
9
|
+
|
|
|
10
|
+ // This sample code is provided "AS IS" with no warranties,
|
|
|
11
|
+
|
|
|
12
|
+ // and confers no rights.
|
|
|
13
|
+
|
|
|
14
|
+ //
|
|
|
15
|
+
|
|
|
16
|
+ // ATTENTION: This sample is designed to be more of a
|
|
|
17
|
+
|
|
|
18
|
+ // tutorial rather than something you can copy and paste in
|
|
|
19
|
+
|
|
|
20
|
+ // the production code!
|
|
|
21
|
+
|
|
|
22
|
+ //
|
|
|
23
|
+
|
|
|
24
|
+
|
|
|
25
|
+
|
|
|
26
|
+
|
|
|
27
|
+
|
|
|
28
|
+
|
|
|
29
|
+ //
|
|
|
30
|
+
|
|
|
31
|
+ // Sample encrypt/decrypt functions
|
|
|
32
|
+
|
|
|
33
|
+ // Parameter checks and error handling
|
|
|
34
|
+
|
|
|
35
|
+ // are ommited for better readability
|
|
|
36
|
+
|
|
|
37
|
+ //
|
|
|
38
|
+
|
|
|
39
|
+
|
|
|
40
|
+ public class EncDec
|
|
|
41
|
+ {
|
|
|
42
|
+ // Encrypt a byte array into a byte array using a key and an IV
|
|
|
43
|
+
|
|
|
44
|
+ public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
|
|
|
45
|
+ {
|
|
|
46
|
+ // Create a MemoryStream to accept the encrypted bytes
|
|
|
47
|
+
|
|
|
48
|
+ MemoryStream ms = new MemoryStream();
|
|
|
49
|
+
|
|
|
50
|
+ // Create a symmetric algorithm.
|
|
|
51
|
+
|
|
|
52
|
+ // We are going to use Rijndael because it is strong and
|
|
|
53
|
+
|
|
|
54
|
+ // available on all platforms.
|
|
|
55
|
+
|
|
|
56
|
+ // You can use other algorithms, to do so substitute the
|
|
|
57
|
+
|
|
|
58
|
+ // next line with something like
|
|
|
59
|
+
|
|
|
60
|
+ // TripleDES alg = TripleDES.Create();
|
|
|
61
|
+
|
|
|
62
|
+ Rijndael alg = Rijndael.Create();
|
|
|
63
|
+
|
|
|
64
|
+ // Now set the key and the IV.
|
|
|
65
|
+
|
|
|
66
|
+ // We need the IV (Initialization Vector) because
|
|
|
67
|
+
|
|
|
68
|
+ // the algorithm is operating in its default
|
|
|
69
|
+
|
|
|
70
|
+ // mode called CBC (Cipher Block Chaining).
|
|
|
71
|
+
|
|
|
72
|
+ // The IV is XORed with the first block (8 byte)
|
|
|
73
|
+
|
|
|
74
|
+ // of the data before it is encrypted, and then each
|
|
|
75
|
+
|
|
|
76
|
+ // encrypted block is XORed with the
|
|
|
77
|
+
|
|
|
78
|
+ // following block of plaintext.
|
|
|
79
|
+
|
|
|
80
|
+ // This is done to make encryption more secure.
|
|
|
81
|
+
|
|
|
82
|
+
|
|
|
83
|
+ // There is also a mode called ECB which does not need an IV,
|
|
|
84
|
+
|
|
|
85
|
+ // but it is much less secure.
|
|
|
86
|
+
|
|
|
87
|
+ alg.Key = Key;
|
|
|
88
|
+ alg.IV = IV;
|
|
|
89
|
+
|
|
|
90
|
+ // Create a CryptoStream through which we are going to be
|
|
|
91
|
+
|
|
|
92
|
+ // pumping our data.
|
|
|
93
|
+
|
|
|
94
|
+ // CryptoStreamMode.Write means that we are going to be
|
|
|
95
|
+
|
|
|
96
|
+ // writing data to the stream and the output will be written
|
|
|
97
|
+
|
|
|
98
|
+ // in the MemoryStream we have provided.
|
|
|
99
|
+
|
|
|
100
|
+ CryptoStream cs = new CryptoStream(ms,
|
|
|
101
|
+ alg.CreateEncryptor(), CryptoStreamMode.Write);
|
|
|
102
|
+
|
|
|
103
|
+ // Write the data and make it do the encryption
|
|
|
104
|
+
|
|
|
105
|
+ cs.Write(clearData, 0, clearData.Length);
|
|
|
106
|
+
|
|
|
107
|
+ // Close the crypto stream (or do FlushFinalBlock).
|
|
|
108
|
+
|
|
|
109
|
+ // This will tell it that we have done our encryption and
|
|
|
110
|
+
|
|
|
111
|
+ // there is no more data coming in,
|
|
|
112
|
+
|
|
|
113
|
+ // and it is now a good time to apply the padding and
|
|
|
114
|
+
|
|
|
115
|
+ // finalize the encryption process.
|
|
|
116
|
+
|
|
|
117
|
+ cs.Close();
|
|
|
118
|
+
|
|
|
119
|
+ // Now get the encrypted data from the MemoryStream.
|
|
|
120
|
+
|
|
|
121
|
+ // Some people make a mistake of using GetBuffer() here,
|
|
|
122
|
+
|
|
|
123
|
+ // which is not the right way.
|
|
|
124
|
+
|
|
|
125
|
+ byte[] encryptedData = ms.ToArray();
|
|
|
126
|
+
|
|
|
127
|
+ return encryptedData;
|
|
|
128
|
+ }
|
|
|
129
|
+
|
|
|
130
|
+ // Encrypt a string into a string using a password
|
|
|
131
|
+
|
|
|
132
|
+ // Uses Encrypt(byte[], byte[], byte[])
|
|
|
133
|
+
|
|
|
134
|
+
|
|
|
135
|
+ public static string Encrypt(string clearText, string Password)
|
|
|
136
|
+ {
|
|
|
137
|
+ // First we need to turn the input string into a byte array.
|
|
|
138
|
+
|
|
|
139
|
+ byte[] clearBytes =
|
|
|
140
|
+ System.Text.Encoding.Unicode.GetBytes(clearText);
|
|
|
141
|
+
|
|
|
142
|
+ // Then, we need to turn the password into Key and IV
|
|
|
143
|
+
|
|
|
144
|
+ // We are using salt to make it harder to guess our key
|
|
|
145
|
+
|
|
|
146
|
+ // using a dictionary attack -
|
|
|
147
|
+
|
|
|
148
|
+ // trying to guess a password by enumerating all possible words.
|
|
|
149
|
+
|
|
|
150
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
151
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
|
|
|
152
|
+ 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
153
|
+
|
|
|
154
|
+ // Now get the key/IV and do the encryption using the
|
|
|
155
|
+
|
|
|
156
|
+ // function that accepts byte arrays.
|
|
|
157
|
+
|
|
|
158
|
+ // Using PasswordDeriveBytes object we are first getting
|
|
|
159
|
+
|
|
|
160
|
+ // 32 bytes for the Key
|
|
|
161
|
+
|
|
|
162
|
+ // (the default Rijndael key length is 256bit = 32bytes)
|
|
|
163
|
+
|
|
|
164
|
+ // and then 16 bytes for the IV.
|
|
|
165
|
+
|
|
|
166
|
+ // IV should always be the block size, which is by default
|
|
|
167
|
+
|
|
|
168
|
+ // 16 bytes (128 bit) for Rijndael.
|
|
|
169
|
+
|
|
|
170
|
+ // If you are using DES/TripleDES/RC2 the block size is
|
|
|
171
|
+
|
|
|
172
|
+ // 8 bytes and so should be the IV size.
|
|
|
173
|
+
|
|
|
174
|
+ // You can also read KeySize/BlockSize properties off
|
|
|
175
|
+
|
|
|
176
|
+ // the algorithm to find out the sizes.
|
|
|
177
|
+
|
|
|
178
|
+ byte[] encryptedData = Encrypt(clearBytes,
|
|
|
179
|
+ pdb.GetBytes(32), pdb.GetBytes(16));
|
|
|
180
|
+
|
|
|
181
|
+ // Now we need to turn the resulting byte array into a string.
|
|
|
182
|
+
|
|
|
183
|
+ // A common mistake would be to use an Encoding class for that.
|
|
|
184
|
+
|
|
|
185
|
+ //It does not work because not all byte values can be
|
|
|
186
|
+
|
|
|
187
|
+ // represented by characters.
|
|
|
188
|
+
|
|
|
189
|
+ // We are going to be using Base64 encoding that is designed
|
|
|
190
|
+
|
|
|
191
|
+ //exactly for what we are trying to do.
|
|
|
192
|
+
|
|
|
193
|
+ return Convert.ToBase64String(encryptedData);
|
|
|
194
|
+
|
|
|
195
|
+ }
|
|
|
196
|
+
|
|
|
197
|
+ // Encrypt bytes into bytes using a password
|
|
|
198
|
+
|
|
|
199
|
+ // Uses Encrypt(byte[], byte[], byte[])
|
|
|
200
|
+
|
|
|
201
|
+
|
|
|
202
|
+ public static byte[] Encrypt(byte[] clearData, string Password)
|
|
|
203
|
+ {
|
|
|
204
|
+ // We need to turn the password into Key and IV.
|
|
|
205
|
+
|
|
|
206
|
+ // We are using salt to make it harder to guess our key
|
|
|
207
|
+
|
|
|
208
|
+ // using a dictionary attack -
|
|
|
209
|
+
|
|
|
210
|
+ // trying to guess a password by enumerating all possible words.
|
|
|
211
|
+
|
|
|
212
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
213
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
|
|
|
214
|
+ 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
215
|
+
|
|
|
216
|
+ // Now get the key/IV and do the encryption using the function
|
|
|
217
|
+
|
|
|
218
|
+ // that accepts byte arrays.
|
|
|
219
|
+
|
|
|
220
|
+ // Using PasswordDeriveBytes object we are first getting
|
|
|
221
|
+
|
|
|
222
|
+ // 32 bytes for the Key
|
|
|
223
|
+
|
|
|
224
|
+ // (the default Rijndael key length is 256bit = 32bytes)
|
|
|
225
|
+
|
|
|
226
|
+ // and then 16 bytes for the IV.
|
|
|
227
|
+
|
|
|
228
|
+ // IV should always be the block size, which is by default
|
|
|
229
|
+
|
|
|
230
|
+ // 16 bytes (128 bit) for Rijndael.
|
|
|
231
|
+
|
|
|
232
|
+ // If you are using DES/TripleDES/RC2 the block size is 8
|
|
|
233
|
+
|
|
|
234
|
+ // bytes and so should be the IV size.
|
|
|
235
|
+
|
|
|
236
|
+ // You can also read KeySize/BlockSize properties off the
|
|
|
237
|
+
|
|
|
238
|
+ // algorithm to find out the sizes.
|
|
|
239
|
+
|
|
|
240
|
+ return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));
|
|
|
241
|
+
|
|
|
242
|
+ }
|
|
|
243
|
+
|
|
|
244
|
+ // Encrypt a file into another file using a password
|
|
|
245
|
+
|
|
|
246
|
+ public static void Encrypt(string fileIn,
|
|
|
247
|
+ string fileOut, string Password)
|
|
|
248
|
+ {
|
|
|
249
|
+
|
|
|
250
|
+ // First we are going to open the file streams
|
|
|
251
|
+
|
|
|
252
|
+ FileStream fsIn = new FileStream(fileIn,
|
|
|
253
|
+ FileMode.Open, FileAccess.Read);
|
|
|
254
|
+ FileStream fsOut = new FileStream(fileOut,
|
|
|
255
|
+ FileMode.OpenOrCreate, FileAccess.Write);
|
|
|
256
|
+
|
|
|
257
|
+ // Then we are going to derive a Key and an IV from the
|
|
|
258
|
+
|
|
|
259
|
+ // Password and create an algorithm
|
|
|
260
|
+
|
|
|
261
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
262
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
|
|
|
263
|
+ 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
264
|
+
|
|
|
265
|
+ Rijndael alg = Rijndael.Create();
|
|
|
266
|
+ alg.Key = pdb.GetBytes(32);
|
|
|
267
|
+ alg.IV = pdb.GetBytes(16);
|
|
|
268
|
+
|
|
|
269
|
+ // Now create a crypto stream through which we are going
|
|
|
270
|
+
|
|
|
271
|
+ // to be pumping data.
|
|
|
272
|
+
|
|
|
273
|
+ // Our fileOut is going to be receiving the encrypted bytes.
|
|
|
274
|
+
|
|
|
275
|
+ CryptoStream cs = new CryptoStream(fsOut,
|
|
|
276
|
+ alg.CreateEncryptor(), CryptoStreamMode.Write);
|
|
|
277
|
+
|
|
|
278
|
+ // Now will will initialize a buffer and will be processing
|
|
|
279
|
+
|
|
|
280
|
+ // the input file in chunks.
|
|
|
281
|
+
|
|
|
282
|
+ // This is done to avoid reading the whole file (which can
|
|
|
283
|
+
|
|
|
284
|
+ // be huge) into memory.
|
|
|
285
|
+
|
|
|
286
|
+ int bufferLen = 4096;
|
|
|
287
|
+ byte[] buffer = new byte[bufferLen];
|
|
|
288
|
+ int bytesRead;
|
|
|
289
|
+
|
|
|
290
|
+ do {
|
|
|
291
|
+ // read a chunk of data from the input file
|
|
|
292
|
+
|
|
|
293
|
+ bytesRead = fsIn.Read(buffer, 0, bufferLen);
|
|
|
294
|
+
|
|
|
295
|
+ // encrypt it
|
|
|
296
|
+
|
|
|
297
|
+ cs.Write(buffer, 0, bytesRead);
|
|
|
298
|
+ } while(bytesRead != 0);
|
|
|
299
|
+
|
|
|
300
|
+ // close everything
|
|
|
301
|
+
|
|
|
302
|
+
|
|
|
303
|
+ // this will also close the unrelying fsOut stream
|
|
|
304
|
+
|
|
|
305
|
+ cs.Close();
|
|
|
306
|
+ fsIn.Close();
|
|
|
307
|
+ }
|
|
|
308
|
+
|
|
|
309
|
+ // Decrypt a byte array into a byte array using a key and an IV
|
|
|
310
|
+
|
|
|
311
|
+ public static byte[] Decrypt(byte[] cipherData,
|
|
|
312
|
+ byte[] Key, byte[] IV)
|
|
|
313
|
+ {
|
|
|
314
|
+ // Create a MemoryStream that is going to accept the
|
|
|
315
|
+
|
|
|
316
|
+ // decrypted bytes
|
|
|
317
|
+
|
|
|
318
|
+ MemoryStream ms = new MemoryStream();
|
|
|
319
|
+
|
|
|
320
|
+ // Create a symmetric algorithm.
|
|
|
321
|
+
|
|
|
322
|
+ // We are going to use Rijndael because it is strong and
|
|
|
323
|
+
|
|
|
324
|
+ // available on all platforms.
|
|
|
325
|
+
|
|
|
326
|
+ // You can use other algorithms, to do so substitute the next
|
|
|
327
|
+
|
|
|
328
|
+ // line with something like
|
|
|
329
|
+
|
|
|
330
|
+ // TripleDES alg = TripleDES.Create();
|
|
|
331
|
+
|
|
|
332
|
+ Rijndael alg = Rijndael.Create();
|
|
|
333
|
+
|
|
|
334
|
+ // Now set the key and the IV.
|
|
|
335
|
+
|
|
|
336
|
+ // We need the IV (Initialization Vector) because the algorithm
|
|
|
337
|
+
|
|
|
338
|
+ // is operating in its default
|
|
|
339
|
+
|
|
|
340
|
+ // mode called CBC (Cipher Block Chaining). The IV is XORed with
|
|
|
341
|
+
|
|
|
342
|
+ // the first block (8 byte)
|
|
|
343
|
+
|
|
|
344
|
+ // of the data after it is decrypted, and then each decrypted
|
|
|
345
|
+
|
|
|
346
|
+ // block is XORed with the previous
|
|
|
347
|
+
|
|
|
348
|
+ // cipher block. This is done to make encryption more secure.
|
|
|
349
|
+
|
|
|
350
|
+ // There is also a mode called ECB which does not need an IV,
|
|
|
351
|
+
|
|
|
352
|
+ // but it is much less secure.
|
|
|
353
|
+
|
|
|
354
|
+ alg.Key = Key;
|
|
|
355
|
+ alg.IV = IV;
|
|
|
356
|
+
|
|
|
357
|
+ // Create a CryptoStream through which we are going to be
|
|
|
358
|
+
|
|
|
359
|
+ // pumping our data.
|
|
|
360
|
+
|
|
|
361
|
+ // CryptoStreamMode.Write means that we are going to be
|
|
|
362
|
+
|
|
|
363
|
+ // writing data to the stream
|
|
|
364
|
+
|
|
|
365
|
+ // and the output will be written in the MemoryStream
|
|
|
366
|
+
|
|
|
367
|
+ // we have provided.
|
|
|
368
|
+
|
|
|
369
|
+ CryptoStream cs = new CryptoStream(ms,
|
|
|
370
|
+ alg.CreateDecryptor(), CryptoStreamMode.Write);
|
|
|
371
|
+
|
|
|
372
|
+ // Write the data and make it do the decryption
|
|
|
373
|
+
|
|
|
374
|
+ cs.Write(cipherData, 0, cipherData.Length);
|
|
|
375
|
+
|
|
|
376
|
+ // Close the crypto stream (or do FlushFinalBlock).
|
|
|
377
|
+
|
|
|
378
|
+ // This will tell it that we have done our decryption
|
|
|
379
|
+
|
|
|
380
|
+ // and there is no more data coming in,
|
|
|
381
|
+
|
|
|
382
|
+ // and it is now a good time to remove the padding
|
|
|
383
|
+
|
|
|
384
|
+ // and finalize the decryption process.
|
|
|
385
|
+
|
|
|
386
|
+ cs.Close();
|
|
|
387
|
+
|
|
|
388
|
+ // Now get the decrypted data from the MemoryStream.
|
|
|
389
|
+
|
|
|
390
|
+ // Some people make a mistake of using GetBuffer() here,
|
|
|
391
|
+
|
|
|
392
|
+ // which is not the right way.
|
|
|
393
|
+
|
|
|
394
|
+ byte[] decryptedData = ms.ToArray();
|
|
|
395
|
+
|
|
|
396
|
+ return decryptedData;
|
|
|
397
|
+ }
|
|
|
398
|
+
|
|
|
399
|
+ // Decrypt a string into a string using a password
|
|
|
400
|
+
|
|
|
401
|
+ // Uses Decrypt(byte[], byte[], byte[])
|
|
|
402
|
+
|
|
|
403
|
+
|
|
|
404
|
+ public static string Decrypt(string cipherText, string Password)
|
|
|
405
|
+ {
|
|
|
406
|
+ // First we need to turn the input string into a byte array.
|
|
|
407
|
+
|
|
|
408
|
+ // We presume that Base64 encoding was used
|
|
|
409
|
+
|
|
|
410
|
+ byte[] cipherBytes = Convert.FromBase64String(cipherText);
|
|
|
411
|
+
|
|
|
412
|
+ // Then, we need to turn the password into Key and IV
|
|
|
413
|
+
|
|
|
414
|
+ // We are using salt to make it harder to guess our key
|
|
|
415
|
+
|
|
|
416
|
+ // using a dictionary attack -
|
|
|
417
|
+
|
|
|
418
|
+ // trying to guess a password by enumerating all possible words.
|
|
|
419
|
+
|
|
|
420
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
421
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65,
|
|
|
422
|
+ 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
423
|
+
|
|
|
424
|
+ // Now get the key/IV and do the decryption using
|
|
|
425
|
+
|
|
|
426
|
+ // the function that accepts byte arrays.
|
|
|
427
|
+
|
|
|
428
|
+ // Using PasswordDeriveBytes object we are first
|
|
|
429
|
+
|
|
|
430
|
+ // getting 32 bytes for the Key
|
|
|
431
|
+
|
|
|
432
|
+ // (the default Rijndael key length is 256bit = 32bytes)
|
|
|
433
|
+
|
|
|
434
|
+ // and then 16 bytes for the IV.
|
|
|
435
|
+
|
|
|
436
|
+ // IV should always be the block size, which is by
|
|
|
437
|
+
|
|
|
438
|
+ // default 16 bytes (128 bit) for Rijndael.
|
|
|
439
|
+
|
|
|
440
|
+ // If you are using DES/TripleDES/RC2 the block size is
|
|
|
441
|
+
|
|
|
442
|
+ // 8 bytes and so should be the IV size.
|
|
|
443
|
+
|
|
|
444
|
+ // You can also read KeySize/BlockSize properties off
|
|
|
445
|
+
|
|
|
446
|
+ // the algorithm to find out the sizes.
|
|
|
447
|
+
|
|
|
448
|
+ byte[] decryptedData = Decrypt(cipherBytes,
|
|
|
449
|
+ pdb.GetBytes(32), pdb.GetBytes(16));
|
|
|
450
|
+
|
|
|
451
|
+ // Now we need to turn the resulting byte array into a string.
|
|
|
452
|
+
|
|
|
453
|
+ // A common mistake would be to use an Encoding class for that.
|
|
|
454
|
+
|
|
|
455
|
+ // It does not work
|
|
|
456
|
+
|
|
|
457
|
+ // because not all byte values can be represented by characters.
|
|
|
458
|
+
|
|
|
459
|
+ // We are going to be using Base64 encoding that is
|
|
|
460
|
+
|
|
|
461
|
+ // designed exactly for what we are trying to do.
|
|
|
462
|
+
|
|
|
463
|
+ return System.Text.Encoding.Unicode.GetString(decryptedData);
|
|
|
464
|
+ }
|
|
|
465
|
+
|
|
|
466
|
+ // Decrypt bytes into bytes using a password
|
|
|
467
|
+
|
|
|
468
|
+ // Uses Decrypt(byte[], byte[], byte[])
|
|
|
469
|
+
|
|
|
470
|
+
|
|
|
471
|
+ public static byte[] Decrypt(byte[] cipherData, string Password)
|
|
|
472
|
+ {
|
|
|
473
|
+ // We need to turn the password into Key and IV.
|
|
|
474
|
+
|
|
|
475
|
+ // We are using salt to make it harder to guess our key
|
|
|
476
|
+
|
|
|
477
|
+ // using a dictionary attack -
|
|
|
478
|
+
|
|
|
479
|
+ // trying to guess a password by enumerating all possible words.
|
|
|
480
|
+
|
|
|
481
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
482
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
|
|
|
483
|
+ 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
484
|
+
|
|
|
485
|
+ // Now get the key/IV and do the Decryption using the
|
|
|
486
|
+
|
|
|
487
|
+ //function that accepts byte arrays.
|
|
|
488
|
+
|
|
|
489
|
+ // Using PasswordDeriveBytes object we are first getting
|
|
|
490
|
+
|
|
|
491
|
+ // 32 bytes for the Key
|
|
|
492
|
+
|
|
|
493
|
+ // (the default Rijndael key length is 256bit = 32bytes)
|
|
|
494
|
+
|
|
|
495
|
+ // and then 16 bytes for the IV.
|
|
|
496
|
+
|
|
|
497
|
+ // IV should always be the block size, which is by default
|
|
|
498
|
+
|
|
|
499
|
+ // 16 bytes (128 bit) for Rijndael.
|
|
|
500
|
+
|
|
|
501
|
+ // If you are using DES/TripleDES/RC2 the block size is
|
|
|
502
|
+
|
|
|
503
|
+ // 8 bytes and so should be the IV size.
|
|
|
504
|
+
|
|
|
505
|
+
|
|
|
506
|
+ // You can also read KeySize/BlockSize properties off the
|
|
|
507
|
+
|
|
|
508
|
+ // algorithm to find out the sizes.
|
|
|
509
|
+
|
|
|
510
|
+ return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
|
|
|
511
|
+ }
|
|
|
512
|
+
|
|
|
513
|
+ // Decrypt a file into another file using a password
|
|
|
514
|
+
|
|
|
515
|
+ public static void Decrypt(string fileIn,
|
|
|
516
|
+ string fileOut, string Password)
|
|
|
517
|
+ {
|
|
|
518
|
+
|
|
|
519
|
+ // First we are going to open the file streams
|
|
|
520
|
+
|
|
|
521
|
+ FileStream fsIn = new FileStream(fileIn,
|
|
|
522
|
+ FileMode.Open, FileAccess.Read);
|
|
|
523
|
+ FileStream fsOut = new FileStream(fileOut,
|
|
|
524
|
+ FileMode.OpenOrCreate, FileAccess.Write);
|
|
|
525
|
+
|
|
|
526
|
+ // Then we are going to derive a Key and an IV from
|
|
|
527
|
+
|
|
|
528
|
+ // the Password and create an algorithm
|
|
|
529
|
+
|
|
|
530
|
+ PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
|
|
|
531
|
+ new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
|
|
|
532
|
+ 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
|
|
|
533
|
+ Rijndael alg = Rijndael.Create();
|
|
|
534
|
+
|
|
|
535
|
+ alg.Key = pdb.GetBytes(32);
|
|
|
536
|
+ alg.IV = pdb.GetBytes(16);
|
|
|
537
|
+
|
|
|
538
|
+ // Now create a crypto stream through which we are going
|
|
|
539
|
+
|
|
|
540
|
+ // to be pumping data.
|
|
|
541
|
+
|
|
|
542
|
+ // Our fileOut is going to be receiving the Decrypted bytes.
|
|
|
543
|
+
|
|
|
544
|
+ CryptoStream cs = new CryptoStream(fsOut,
|
|
|
545
|
+ alg.CreateDecryptor(), CryptoStreamMode.Write);
|
|
|
546
|
+
|
|
|
547
|
+ // Now will will initialize a buffer and will be
|
|
|
548
|
+
|
|
|
549
|
+ // processing the input file in chunks.
|
|
|
550
|
+
|
|
|
551
|
+ // This is done to avoid reading the whole file (which can be
|
|
|
552
|
+
|
|
|
553
|
+ // huge) into memory.
|
|
|
554
|
+
|
|
|
555
|
+ int bufferLen = 4096;
|
|
|
556
|
+ byte[] buffer = new byte[bufferLen];
|
|
|
557
|
+ int bytesRead;
|
|
|
558
|
+
|
|
|
559
|
+ do {
|
|
|
560
|
+ // read a chunk of data from the input file
|
|
|
561
|
+
|
|
|
562
|
+ bytesRead = fsIn.Read(buffer, 0, bufferLen);
|
|
|
563
|
+
|
|
|
564
|
+ // Decrypt it
|
|
|
565
|
+
|
|
|
566
|
+ cs.Write(buffer, 0, bytesRead);
|
|
|
567
|
+
|
|
|
568
|
+ } while(bytesRead != 0);
|
|
|
569
|
+
|
|
|
570
|
+ // close everything
|
|
|
571
|
+
|
|
|
572
|
+ cs.Close(); // this will also close the unrelying fsOut stream
|
|
|
573
|
+
|
|
|
574
|
+ fsIn.Close();
|
|
|
575
|
+ }
|
|
|
576
|
+ }
|
|
|
577
|
+
|
|
|
578
|
+
|
|
|
579
|
+}
|