Comments
[NovacoinLibrary.git] / Novacoin / CryptoUtils.cs
1 \feffusing System;
2 using System.Security.Cryptography;
3
4 namespace Novacoin
5 {
6     public class CryptoUtils
7     {
8         public static byte[] PBKDF2_Sha256(int dklen, byte[] password, byte[] salt, int iterationCount)
9         {
10             /* Init HMAC state. */
11             using (var hmac = new HMACSHA256(password))
12             {
13                 int hashLength = hmac.HashSize / 8;
14                 if ((hmac.HashSize & 7) != 0)
15                 {
16                     hashLength++;
17                 }
18                 int keyLength = dklen / hashLength;
19                 if ((long)dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
20                 {
21                     throw new ArgumentOutOfRangeException("dklen");
22                 }
23                 if (dklen % hashLength != 0)
24                 {
25                     keyLength++;
26                 }
27                 byte[] extendedkey = new byte[salt.Length + 4];
28                 Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
29                 using (var ms = new System.IO.MemoryStream())
30                 {
31                     /* Iterate through the blocks. */
32                     for (int i = 0; i < keyLength; i++)
33                     {
34                         /* Generate INT(i + 1). */
35                         extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF);
36                         extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF);
37                         extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF);
38                         extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF);
39
40                         /* Compute U_1 = PRF(P, S || INT(i)). */
41                         byte[] u = hmac.ComputeHash(extendedkey);
42                         Array.Clear(extendedkey, salt.Length, 4);
43
44                         /* T_i = U_1 ... */
45                         byte[] f = u;
46                         for (int j = 1; j < iterationCount; j++)
47                         {
48                             /* Compute U_j. */
49                             u = hmac.ComputeHash(u);
50                             for (int k = 0; k < f.Length; k++)
51                             {
52                                 /* ... xor U_j ... */
53                                 f[k] ^= u[k];
54                             }
55                         }
56
57                         /* Copy as many bytes as necessary into memory stream. */
58                         ms.Write(f, 0, f.Length);
59                         Array.Clear(u, 0, u.Length);
60                         Array.Clear(f, 0, f.Length);
61                     }
62                     ms.Position = 0;
63
64                     /* Initialize result array. */
65                     byte[] dk = new byte[dklen];
66
67                     /* Read key from memory stream. */
68                     ms.Read(dk, 0, dklen);
69
70                     ms.Position = 0;
71                     for (long i = 0; i < ms.Length; i++)
72                     {
73                         ms.WriteByte(0);
74                     }
75                     Array.Clear(extendedkey, 0, extendedkey.Length);
76                     return dk;
77                 }
78             }
79         }
80     }
81 }