Move PBKDF2 to new module, add some new Interop methods
authorCryptoManiac <balthazar@yandex.ru>
Wed, 19 Aug 2015 23:43:44 +0000 (02:43 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Wed, 19 Aug 2015 23:43:44 +0000 (02:43 +0300)
Novacoin/CryptoUtils.cs [new file with mode: 0644]
Novacoin/Interop.cs
Novacoin/Novacoin.csproj
Novacoin/ScryptHash256.cs

diff --git a/Novacoin/CryptoUtils.cs b/Novacoin/CryptoUtils.cs
new file mode 100644 (file)
index 0000000..fde2880
--- /dev/null
@@ -0,0 +1,59 @@
+\feffusing System;
+using System.Security.Cryptography;
+
+namespace Novacoin
+{
+    public class CryptoUtils
+    {
+        public static byte[] PBKDF2_Sha256(int dklen, byte[] password, byte[] salt, int iterationCount)
+        {
+            using (var hmac = new HMACSHA256(password))
+            {
+                int hashLength = hmac.HashSize / 8;
+                if ((hmac.HashSize & 7) != 0)
+                    hashLength++;
+                int keyLength = dklen / hashLength;
+                if ((long)dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
+                    throw new ArgumentOutOfRangeException("dklen");
+                if (dklen % hashLength != 0)
+                    keyLength++;
+                byte[] extendedkey = new byte[salt.Length + 4];
+                Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
+                using (var ms = new System.IO.MemoryStream())
+                {
+                    for (int i = 0; i < keyLength; i++)
+                    {
+                        extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF);
+                        extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF);
+                        extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF);
+                        extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF);
+                        byte[] u = hmac.ComputeHash(extendedkey);
+                        Array.Clear(extendedkey, salt.Length, 4);
+                        byte[] f = u;
+                        for (int j = 1; j < iterationCount; j++)
+                        {
+                            u = hmac.ComputeHash(u);
+                            for (int k = 0; k < f.Length; k++)
+                            {
+                                f[k] ^= u[k];
+                            }
+                        }
+                        ms.Write(f, 0, f.Length);
+                        Array.Clear(u, 0, u.Length);
+                        Array.Clear(f, 0, f.Length);
+                    }
+                    byte[] dk = new byte[dklen];
+                    ms.Position = 0;
+                    ms.Read(dk, 0, dklen);
+                    ms.Position = 0;
+                    for (long i = 0; i < ms.Length; i++)
+                    {
+                        ms.WriteByte(0);
+                    }
+                    Array.Clear(extendedkey, 0, extendedkey.Length);
+                    return dk;
+                }
+            }
+        }
+    }
+}
index 57431a3..3bae5e0 100644 (file)
@@ -76,7 +76,6 @@ namespace Novacoin
 
                 return result.ToArray();
             }
-
         }
 
         public static byte[] LEBytes(ushort n)
@@ -269,5 +268,172 @@ namespace Novacoin
             }
             return sb.ToString();
         }
+
+        public static void UInt16ToBE(ushort n, byte[] bs)
+        {
+            bs[0] = (byte)(n >> 8);
+            bs[1] = (byte)(n);
+        }
+
+        public static ushort BEToUInt16(byte[] bs)
+        {
+            ushort n = (ushort)(bs[0] << 8);
+            n |= (ushort)bs[1];
+            return n;
+        }
+
+        public static ushort BEToUInt16(byte[] bs, int off)
+        {
+            ushort n = (ushort)(bs[off] << 8);
+            n |= (ushort)bs[++off];
+            return n;
+        }
+
+        public static void UInt16ToLE(ushort n, byte[] bs)
+        {
+            bs[0] = (byte)(n);
+            bs[1] = (byte)(n >> 8);
+        }
+
+        public static void UInt16ToLE(ushort n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n);
+            bs[++off] = (byte)(n >> 8);
+        }
+
+        public static ushort LEToUInt16(byte[] bs)
+        {
+            ushort n = (ushort)bs[0];
+            n |= (ushort)(bs[1] << 8);
+            return n;
+        }
+
+        public static ushort LEToUInt16(byte[] bs, int off)
+        {
+            ushort n = (ushort)bs[off];
+            n |= (ushort)(bs[++off] << 8);
+            return n;
+        }
+
+        public static void UInt32ToBE(uint n, byte[] bs)
+        {
+            bs[0] = (byte)(n >> 24);
+            bs[1] = (byte)(n >> 16);
+            bs[2] = (byte)(n >> 8);
+            bs[3] = (byte)(n);
+        }
+
+        public static void UInt32ToBE(uint n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n >> 24);
+            bs[++off] = (byte)(n >> 16);
+            bs[++off] = (byte)(n >> 8);
+            bs[++off] = (byte)(n);
+        }
+
+        public static uint BEToUInt32(byte[] bs)
+        {
+            uint n = (uint)bs[0] << 24;
+            n |= (uint)bs[1] << 16;
+            n |= (uint)bs[2] << 8;
+            n |= (uint)bs[3];
+            return n;
+        }
+
+        public static uint BEToUInt32(byte[] bs, int off)
+        {
+            uint n = (uint)bs[off] << 24;
+            n |= (uint)bs[++off] << 16;
+            n |= (uint)bs[++off] << 8;
+            n |= (uint)bs[++off];
+            return n;
+        }
+
+        public static ulong BEToUInt64(byte[] bs)
+        {
+            uint hi = BEToUInt32(bs);
+            uint lo = BEToUInt32(bs, 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        public static ulong BEToUInt64(byte[] bs, int off)
+        {
+            uint hi = BEToUInt32(bs, off);
+            uint lo = BEToUInt32(bs, off + 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        public static void UInt64ToBE(ulong n, byte[] bs)
+        {
+            UInt32ToBE((uint)(n >> 32), bs);
+            UInt32ToBE((uint)(n), bs, 4);
+        }
+
+        public static void UInt64ToBE(ulong n, byte[] bs, int off)
+        {
+            UInt32ToBE((uint)(n >> 32), bs, off);
+            UInt32ToBE((uint)(n), bs, off + 4);
+        }
+
+        public static void UInt32ToLE(uint n, byte[] bs)
+        {
+            bs[0] = (byte)(n);
+            bs[1] = (byte)(n >> 8);
+            bs[2] = (byte)(n >> 16);
+            bs[3] = (byte)(n >> 24);
+        }
+
+        public static void UInt32ToLE(uint n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n);
+            bs[++off] = (byte)(n >> 8);
+            bs[++off] = (byte)(n >> 16);
+            bs[++off] = (byte)(n >> 24);
+        }
+
+        public static uint LEToUInt32(byte[] bs)
+        {
+            uint n = (uint)bs[0];
+            n |= (uint)bs[1] << 8;
+            n |= (uint)bs[2] << 16;
+            n |= (uint)bs[3] << 24;
+            return n;
+        }
+
+        public static uint LEToUInt32(byte[] bs, int off)
+        {
+            uint n = (uint)bs[off];
+            n |= (uint)bs[++off] << 8;
+            n |= (uint)bs[++off] << 16;
+            n |= (uint)bs[++off] << 24;
+            return n;
+        }
+
+        public static ulong LEToUInt64(byte[] bs)
+        {
+            uint lo = LEToUInt32(bs);
+            uint hi = LEToUInt32(bs, 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        public static ulong LEToUInt64(byte[] bs, int off)
+        {
+            uint lo = LEToUInt32(bs, off);
+            uint hi = LEToUInt32(bs, off + 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        public static void UInt64ToLE(ulong n, byte[] bs)
+        {
+            UInt32ToLE((uint)(n), bs);
+            UInt32ToLE((uint)(n >> 32), bs, 4);
+        }
+
+        public static void UInt64ToLE(ulong n, byte[] bs, int off)
+        {
+            UInt32ToLE((uint)(n), bs, off);
+            UInt32ToLE((uint)(n >> 32), bs, off + 4);
+        }
+
     }
 }
index 2c5e1b2..f02b222 100644 (file)
@@ -43,6 +43,7 @@
     <Compile Include="CKeyPair.cs" />
     <Compile Include="CNovacoinAddress.cs" />
     <Compile Include="CPubKey.cs" />
+    <Compile Include="CryptoUtils.cs" />
     <Compile Include="CScriptID.cs" />
     <Compile Include="Hash.cs" />
     <Compile Include="Interop.cs" />
index ae4f0dd..90c2f8f 100644 (file)
@@ -2,8 +2,6 @@
 using System.Collections.Generic;
 using System.Linq;
 
-using System.Security.Cryptography;
-
 namespace Novacoin
 {
     /// <summary>
@@ -31,7 +29,7 @@ namespace Novacoin
             uint[] V = new uint[(131072 + 63) / sizeof(uint)];
 
             byte[] dataBytes = inputBytes.ToArray();
-            byte[] keyBytes1 = PBKDF2Sha256GetBytes(128, dataBytes, dataBytes, 1);
+            byte[] keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, dataBytes, dataBytes, 1);
             uint[] X = Interop.ToUInt32Array(keyBytes1);
 
             uint i, j, k;
@@ -52,62 +50,11 @@ namespace Novacoin
             }
 
             byte[] xBytes = Interop.LEBytes(X);
-            byte[] keyBytes2 = PBKDF2Sha256GetBytes(32, dataBytes, xBytes, 1);
+            byte[] keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, dataBytes, xBytes, 1);
 
             return new ScryptHash256(keyBytes2);
         }
 
-        private static byte[] PBKDF2Sha256GetBytes(int dklen, byte[] password, byte[] salt, int iterationCount)
-        {
-            using (var hmac = new HMACSHA256(password))
-            {
-                int hashLength = hmac.HashSize / 8;
-                if ((hmac.HashSize & 7) != 0)
-                    hashLength++;
-                int keyLength = dklen / hashLength;
-                if ((long)dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
-                    throw new ArgumentOutOfRangeException("dklen");
-                if (dklen % hashLength != 0)
-                    keyLength++;
-                byte[] extendedkey = new byte[salt.Length + 4];
-                Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
-                using (var ms = new System.IO.MemoryStream())
-                {
-                    for (int i = 0; i < keyLength; i++)
-                    {
-                        extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF);
-                        extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF);
-                        extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF);
-                        extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF);
-                        byte[] u = hmac.ComputeHash(extendedkey);
-                        Array.Clear(extendedkey, salt.Length, 4);
-                        byte[] f = u;
-                        for (int j = 1; j < iterationCount; j++)
-                        {
-                            u = hmac.ComputeHash(u);
-                            for (int k = 0; k < f.Length; k++)
-                            {
-                                f[k] ^= u[k];
-                            }
-                        }
-                        ms.Write(f, 0, f.Length);
-                        Array.Clear(u, 0, u.Length);
-                        Array.Clear(f, 0, f.Length);
-                    }
-                    byte[] dk = new byte[dklen];
-                    ms.Position = 0;
-                    ms.Read(dk, 0, dklen);
-                    ms.Position = 0;
-                    for (long i = 0; i < ms.Length; i++)
-                    {
-                        ms.WriteByte(0);
-                    }
-                    Array.Clear(extendedkey, 0, extendedkey.Length);
-                    return dk;
-                }
-            }
-        }
-
         private static void xor_salsa8(ref uint[] B, int indexB, ref uint[] Bx, int indexBx)
         {
             uint x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15;