From 5f1c284906c75b1c579357db468239d47c5b8707 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Mon, 24 Aug 2015 00:02:23 +0300 Subject: [PATCH] Use BouncyCastle hashing functions --- Novacoin/CBlock.cs | 28 ++++++------------ Novacoin/CBlockHeader.cs | 4 +- Novacoin/CScript.cs | 2 +- Novacoin/CTransaction.cs | 4 +- Novacoin/Hash.cs | 18 ------------ Novacoin/Hash160.cs | 25 ++++++++++------ Novacoin/Hash256.cs | 69 +++++++++++++++++++++++++++++++++++++-------- Novacoin/RIPEMD160.cs | 18 ++++++------ Novacoin/SHA1.cs | 15 +++++---- Novacoin/SHA256.cs | 16 ++++++---- Novacoin/ScriptCode.cs | 9 ++--- Novacoin/ScryptHash256.cs | 10 ++---- 12 files changed, 122 insertions(+), 96 deletions(-) diff --git a/Novacoin/CBlock.cs b/Novacoin/CBlock.cs index 9964edd..7511fdf 100644 --- a/Novacoin/CBlock.cs +++ b/Novacoin/CBlock.cs @@ -178,33 +178,25 @@ namespace Novacoin foreach (var tx in vtx) { - merkleTree.AddRange(tx.Hash.hashBytes); + merkleTree.AddRange(Hash256.ComputeRaw256(tx.Bytes)); } - var hasher = new SHA256Managed(); - hasher.Initialize(); - - int j = 0; - for (int nSize = vtx.Length; nSize > 1; nSize = (nSize + 1) / 2) + int levelOffset = 0; + for (int nLevelSize = vtx.Length; nLevelSize > 1; nLevelSize = (nLevelSize + 1) / 2) { - for (int i = 0; i < nSize; i += 2) + for (int nLeft = 0; nLeft < nLevelSize; nLeft += 2) { - int i2 = Math.Min(i + 1, nSize - 1); - - var pair = new List(); - - pair.AddRange(merkleTree.GetRange((j + i)*32, 32)); - pair.AddRange(merkleTree.GetRange((j + i2)*32, 32)); + int nRight = Math.Min(nLeft + 1, nLevelSize - 1); - var digest1 = hasher.ComputeHash(pair.ToArray()); - var digest2 = hasher.ComputeHash(digest1); + var left = merkleTree.GetRange((levelOffset + nLeft) * 32, 32).ToArray(); + var right = merkleTree.GetRange((levelOffset + nRight) * 32, 32).ToArray(); - merkleTree.AddRange(digest2); + merkleTree.AddRange(Hash256.ComputeRaw256(ref left, ref right)); } - j += nSize; + levelOffset += nLevelSize; } - return (merkleTree.Count == 0) ? new Hash256() : new Hash256(merkleTree.GetRange(merkleTree.Count-32, 32)); + return (merkleTree.Count == 0) ? new Hash256() : new Hash256(merkleTree.GetRange(merkleTree.Count-32, 32).ToArray()); } } diff --git a/Novacoin/CBlockHeader.cs b/Novacoin/CBlockHeader.cs index cc753c4..167e32e 100644 --- a/Novacoin/CBlockHeader.cs +++ b/Novacoin/CBlockHeader.cs @@ -89,7 +89,7 @@ namespace Novacoin /// Convert current block header instance into sequence of bytes /// /// Byte sequence - public IList Bytes + public byte[] Bytes { get { @@ -102,7 +102,7 @@ namespace Novacoin r.AddRange(BitConverter.GetBytes(nBits)); r.AddRange(BitConverter.GetBytes(nNonce)); - return r; + return r.ToArray(); } } diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index 1bc347a..9149d34 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -451,7 +451,7 @@ namespace Novacoin public CScriptID ScriptID { - get { return new CScriptID(Hash160.Compute160(codeBytes)); } + get { return new CScriptID(Hash160.Compute160(codeBytes.ToArray())); } } /// diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index 3557398..091b442 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -189,7 +189,7 @@ namespace Novacoin /// /// A sequence of bytes, which corresponds to the current state of CTransaction. /// - public IList Bytes + public byte[] Bytes { get { @@ -257,7 +257,7 @@ namespace Novacoin resultBytes.AddRange(BitConverter.GetBytes(nLockTime)); - return resultBytes; + return resultBytes.ToArray(); } } diff --git a/Novacoin/Hash.cs b/Novacoin/Hash.cs index 3d757f1..b9e6d0c 100644 --- a/Novacoin/Hash.cs +++ b/Novacoin/Hash.cs @@ -17,22 +17,13 @@ */ using System; -using System.Security.Cryptography; -using System.Collections.Generic; using System.Linq; -using System.Numerics; - namespace Novacoin { public abstract class Hash { /// - /// Computes the SHA256 hash for the input data using the managed library. - /// - protected static SHA256Managed _hasher256 = new SHA256Managed(); - - /// /// Array of digest bytes. /// protected byte[] _hashBytes = null; @@ -61,15 +52,6 @@ namespace Novacoin /// /// Initializes a new instance of Hash class /// - /// List of bytes - public Hash(IEnumerable bytes, int skip = 0) - { - _hashBytes = bytes.Skip(skip).Take(hashSize).ToArray(); - } - - /// - /// Initializes a new instance of Hash class - /// /// Array of bytes public Hash(byte[] bytes, int offset = 0) { diff --git a/Novacoin/Hash160.cs b/Novacoin/Hash160.cs index 272527b..df73f99 100644 --- a/Novacoin/Hash160.cs +++ b/Novacoin/Hash160.cs @@ -17,8 +17,7 @@ */ using System.Linq; -using System.Collections.Generic; -using System.Security.Cryptography; +using Org.BouncyCastle.Crypto.Digests; namespace Novacoin { @@ -30,24 +29,32 @@ namespace Novacoin /// /// Computes RIPEMD160 hash using managed library /// - private static readonly RIPEMD160Managed _hasher160 = new RIPEMD160Managed(); - + //private static readonly RIPEMD160Managed _hasher160 = new RIPEMD160Managed(); + + private static RipeMD160Digest _hasher160 = new RipeMD160Digest(); + private static Sha256Digest _hasher256 = new Sha256Digest(); + // 20 bytes public override int hashSize { - get { return 20; } + get { return _hasher160.GetDigestSize(); } } public Hash160() : base() { } public Hash160(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public Hash160(IEnumerable bytes, int skip = 0) : base(bytes, skip) { } public Hash160(Hash160 h) : base(h) { } - public static Hash160 Compute160(IEnumerable inputBytes) + public static Hash160 Compute160(byte[] inputBytes) { var dataBytes = inputBytes.ToArray(); - var digest1 = _hasher256.ComputeHash(dataBytes, 0, dataBytes.Length); - var digest2 = _hasher160.ComputeHash(digest1, 0, digest1.Length); + + var digest1 = new byte[32]; + var digest2 = new byte[20]; + + _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); + _hasher256.DoFinal(digest1, 0); + _hasher160.BlockUpdate(digest1, 0, digest1.Length); + _hasher160.DoFinal(digest2, 0); return new Hash160(digest2); } diff --git a/Novacoin/Hash256.cs b/Novacoin/Hash256.cs index 2615855..3d3a360 100644 --- a/Novacoin/Hash256.cs +++ b/Novacoin/Hash256.cs @@ -17,36 +17,81 @@ */ -using System.Linq; -using System.Collections.Generic; +using Org.BouncyCastle.Crypto.Digests; namespace Novacoin { - /// - /// Representation of Double SHA-256 hash - /// + /// + /// Representation of Double SHA-256 hash + /// public class Hash256 : Hash { + private static Sha256Digest _hasher256 = new Sha256Digest(); + // 32 bytes public override int hashSize { - get { return 32; } + get { return _hasher256.GetDigestSize(); } } public Hash256() : base() { } public Hash256(byte[] bytes, int offset=0) : base(bytes, offset) { } - public Hash256(IEnumerable bytes, int skip=0) : base(bytes, skip) { } public Hash256(Hash256 h) : base(h) { } + public static Hash256 Compute256(byte[] dataBytes) + { + var digest1 = new byte[32]; + var digest2 = new byte[32]; + + _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); + _hasher256.DoFinal(digest1, 0); + _hasher256.BlockUpdate(digest1, 0, digest1.Length); + _hasher256.DoFinal(digest2, 0); + + return new Hash256(digest2); + } - public static Hash256 Compute256(IEnumerable inputBytes) + public static Hash256 Compute256(ref byte[] input1, ref byte[] input2) { - var dataBytes = inputBytes.ToArray(); - var digest1 = _hasher256.ComputeHash(dataBytes, 0, dataBytes.Length); - var digest2 = _hasher256.ComputeHash(digest1, 0, digest1.Length); + var digest1 = new byte[_hasher256.GetDigestSize()]; + var digest2 = new byte[_hasher256.GetDigestSize()]; + + _hasher256.BlockUpdate(input1, 0, input1.Length); + _hasher256.BlockUpdate(input2, 0, input2.Length); + _hasher256.DoFinal(digest1, 0); + + _hasher256.BlockUpdate(digest1, 0, digest1.Length); + _hasher256.DoFinal(digest2, 0); return new Hash256(digest2); } + + public static byte[] ComputeRaw256(byte[] dataBytes) + { + var digest1 = new byte[32]; + var digest2 = new byte[32]; + + _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); + _hasher256.DoFinal(digest1, 0); + _hasher256.BlockUpdate(digest1, 0, digest1.Length); + _hasher256.DoFinal(digest2, 0); + + return digest2; + } + + public static byte[] ComputeRaw256(ref byte[] input1, ref byte[] input2) + { + var digest1 = new byte[_hasher256.GetDigestSize()]; + var digest2 = new byte[_hasher256.GetDigestSize()]; + + _hasher256.BlockUpdate(input1, 0, input1.Length); + _hasher256.BlockUpdate(input2, 0, input2.Length); + _hasher256.DoFinal(digest1, 0); + + _hasher256.BlockUpdate(digest1, 0, digest1.Length); + _hasher256.DoFinal(digest2, 0); + + return digest2; + } } } - diff --git a/Novacoin/RIPEMD160.cs b/Novacoin/RIPEMD160.cs index 74e25b8..84ce67f 100644 --- a/Novacoin/RIPEMD160.cs +++ b/Novacoin/RIPEMD160.cs @@ -14,10 +14,9 @@ * along with this program. If not, see . */ - +using Org.BouncyCastle.Crypto.Digests; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; namespace Novacoin { @@ -29,23 +28,24 @@ namespace Novacoin /// /// Computes RIPEMD160 hash using managed library /// - private static readonly RIPEMD160Managed _hasher160 = new RIPEMD160Managed(); - + // private static readonly RIPEMD160Managed _hasher160 = new RIPEMD160Managed(); + private static RipeMD160Digest _hasher160 = new RipeMD160Digest(); + // 20 bytes public override int hashSize { - get { return 20; } + get { return _hasher160.GetDigestSize(); } } public RIPEMD160() : base() { } public RIPEMD160(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public RIPEMD160(IEnumerable bytes, int skip = 0) : base(bytes, skip) { } public RIPEMD160(RIPEMD160 h) : base(h) { } - public static RIPEMD160 Compute160(IEnumerable inputBytes) + public static RIPEMD160 Compute160(byte[] inputBytes) { - var dataBytes = inputBytes.ToArray(); - var digest1 = _hasher160.ComputeHash(dataBytes, 0, dataBytes.Length); + var digest1 = new byte[_hasher160.GetDigestSize()]; + _hasher160.BlockUpdate(inputBytes, 0, inputBytes.Length); + _hasher160.DoFinal(digest1, 0); return new RIPEMD160(digest1); } diff --git a/Novacoin/SHA1.cs b/Novacoin/SHA1.cs index 9d31cfa..7ef1755 100644 --- a/Novacoin/SHA1.cs +++ b/Novacoin/SHA1.cs @@ -17,7 +17,7 @@ using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; +using Org.BouncyCastle.Crypto.Digests; namespace Novacoin { @@ -29,24 +29,25 @@ namespace Novacoin /// /// Computes RIPEMD160 hash using managed library /// - private static readonly SHA1Managed _hasher1 = new SHA1Managed(); + private static Sha1Digest _hasher1 = new Sha1Digest(); // 32 bytes public override int hashSize { - get { return 20; } + get { return _hasher1.GetDigestSize(); } } public SHA1() : base() { } public SHA1(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public SHA1(IEnumerable bytes, int skip = 0) : base(bytes, skip) { } public SHA1(SHA1 h) : base(h) { } - public static SHA1 Compute1(IEnumerable inputBytes) + public static SHA1 Compute1(byte[] inputBytes) { - var dataBytes = inputBytes.ToArray(); - var digest1 = _hasher1.ComputeHash(dataBytes, 0, dataBytes.Length); + var digest1 = new byte[_hasher1.GetDigestSize()]; + + _hasher1.BlockUpdate(inputBytes, 0, inputBytes.Length); + _hasher1.DoFinal(digest1, 0); return new SHA1(digest1); } diff --git a/Novacoin/SHA256.cs b/Novacoin/SHA256.cs index 953eaf4..4ceda48 100644 --- a/Novacoin/SHA256.cs +++ b/Novacoin/SHA256.cs @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -using System.Linq; -using System.Collections.Generic; +using Org.BouncyCastle.Crypto.Digests; namespace Novacoin { @@ -26,22 +25,25 @@ namespace Novacoin /// public class SHA256 : Hash { + private static Sha256Digest _hasher256 = new Sha256Digest(); + // 32 bytes public override int hashSize { - get { return 32; } + get { return _hasher256.GetDigestSize(); } } public SHA256() : base() { } public SHA256(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public SHA256(IEnumerable bytes, int skip = 0) : base(bytes, skip) { } public SHA256(SHA256 h) : base(h) { } - public static SHA256 Compute256(IEnumerable inputBytes) + public static SHA256 Compute256(byte[] inputBytes) { - var dataBytes = inputBytes.ToArray(); - var digest1 = _hasher256.ComputeHash(dataBytes, 0, dataBytes.Length); + var digest1 = new byte[_hasher256.GetDigestSize()]; + + _hasher256.BlockUpdate(inputBytes, 0, inputBytes.Length); + _hasher256.DoFinal(digest1, 0); return new SHA256(digest1); } diff --git a/Novacoin/ScriptCode.cs b/Novacoin/ScriptCode.cs index 658a74c..c90bf87 100644 --- a/Novacoin/ScriptCode.cs +++ b/Novacoin/ScriptCode.cs @@ -741,12 +741,11 @@ namespace Novacoin Array.Resize(ref txTmp.vin, 1); } - // Serialize and hash - var b = new List(); - b.AddRange(txTmp.Bytes); - b.AddRange(BitConverter.GetBytes(nHashType)); + // Concatenate and hash + var txBytes = txTmp.Bytes; + var nHashTypeBytes = BitConverter.GetBytes(nHashType); - return Hash256.Compute256(b); + return Hash256.Compute256(ref txBytes, ref nHashTypeBytes); } // diff --git a/Novacoin/ScryptHash256.cs b/Novacoin/ScryptHash256.cs index 0bf4ac4..96b017f 100644 --- a/Novacoin/ScryptHash256.cs +++ b/Novacoin/ScryptHash256.cs @@ -16,7 +16,7 @@ using System; using System.Collections.Generic; -using System.Linq; +//using System.Linq; namespace Novacoin { @@ -33,7 +33,6 @@ namespace Novacoin public ScryptHash256() : base() { } public ScryptHash256(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public ScryptHash256(IEnumerable bytes, int skip = 0) : base(bytes, skip) { } public ScryptHash256(ScryptHash256 h) : base(h) { } /// @@ -41,12 +40,11 @@ namespace Novacoin /// /// Byte sequence to hash /// Hashing result instance - public static ScryptHash256 Compute256(IEnumerable inputBytes) + public static ScryptHash256 Compute256(byte[] inputBytes) { var V = new uint[(131072 + 63) / sizeof(uint)]; - var dataBytes = inputBytes.ToArray(); - var keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, dataBytes, dataBytes, 1); + var keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, (byte[])inputBytes, (byte[])inputBytes, 1); var X = Interop.ToUInt32Array(keyBytes1); for (var i = 0; i < 1024; i++) @@ -68,7 +66,7 @@ namespace Novacoin } var xBytes = Interop.LEBytes(X); - var keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, dataBytes, xBytes, 1); + var keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, (byte[])inputBytes, xBytes, 1); return new ScryptHash256(keyBytes2); } -- 1.7.1