From 2508164a9874b124c7a6036d24c44fba1335834b Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 20 Aug 2015 02:43:44 +0300 Subject: [PATCH] Move PBKDF2 to new module, add some new Interop methods --- Novacoin/CryptoUtils.cs | 59 ++++++++++++++++ Novacoin/Interop.cs | 168 ++++++++++++++++++++++++++++++++++++++++++++- Novacoin/Novacoin.csproj | 1 + Novacoin/ScryptHash256.cs | 57 +--------------- 4 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 Novacoin/CryptoUtils.cs diff --git a/Novacoin/CryptoUtils.cs b/Novacoin/CryptoUtils.cs new file mode 100644 index 0000000..fde2880 --- /dev/null +++ b/Novacoin/CryptoUtils.cs @@ -0,0 +1,59 @@ +using 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; + } + } + } + } +} diff --git a/Novacoin/Interop.cs b/Novacoin/Interop.cs index 57431a3..3bae5e0 100644 --- a/Novacoin/Interop.cs +++ b/Novacoin/Interop.cs @@ -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); + } + } } diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index 2c5e1b2..f02b222 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -43,6 +43,7 @@ + diff --git a/Novacoin/ScryptHash256.cs b/Novacoin/ScryptHash256.cs index ae4f0dd..90c2f8f 100644 --- a/Novacoin/ScryptHash256.cs +++ b/Novacoin/ScryptHash256.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; - namespace Novacoin { /// @@ -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; -- 1.7.1