Move PBKDF2 to new module, add some new Interop methods
[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             using (var hmac = new HMACSHA256(password))
11             {
12                 int hashLength = hmac.HashSize / 8;
13                 if ((hmac.HashSize & 7) != 0)
14                     hashLength++;
15                 int keyLength = dklen / hashLength;
16                 if ((long)dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
17                     throw new ArgumentOutOfRangeException("dklen");
18                 if (dklen % hashLength != 0)
19                     keyLength++;
20                 byte[] extendedkey = new byte[salt.Length + 4];
21                 Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
22                 using (var ms = new System.IO.MemoryStream())
23                 {
24                     for (int i = 0; i < keyLength; i++)
25                     {
26                         extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF);
27                         extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF);
28                         extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF);
29                         extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF);
30                         byte[] u = hmac.ComputeHash(extendedkey);
31                         Array.Clear(extendedkey, salt.Length, 4);
32                         byte[] f = u;
33                         for (int j = 1; j < iterationCount; j++)
34                         {
35                             u = hmac.ComputeHash(u);
36                             for (int k = 0; k < f.Length; k++)
37                             {
38                                 f[k] ^= u[k];
39                             }
40                         }
41                         ms.Write(f, 0, f.Length);
42                         Array.Clear(u, 0, u.Length);
43                         Array.Clear(f, 0, f.Length);
44                     }
45                     byte[] dk = new byte[dklen];
46                     ms.Position = 0;
47                     ms.Read(dk, 0, dklen);
48                     ms.Position = 0;
49                     for (long i = 0; i < ms.Length; i++)
50                     {
51                         ms.WriteByte(0);
52                     }
53                     Array.Clear(extendedkey, 0, extendedkey.Length);
54                     return dk;
55                 }
56             }
57         }
58     }
59 }