示例#1
0
        public Blake2BTests()
        {
            Int32          LIdx;
            IBlake2BConfig LConfig = new Blake2BConfig();

            byte[] LKey = new byte[64];

            for (LIdx = 0; LIdx < LKey.Length; LIdx++)
            {
                LKey[LIdx] = (byte)LIdx;
            }

            LConfig.Key = LKey;

            hash = HashFactory.Crypto.CreateBlake2B();

            HashInstanceWithKey = HashFactory.Crypto.CreateBlake2B(LConfig);

            ExpectedHashOfEmptyData   = "786A02F742015903C6C6FD852552D272912F4740E15847618A86E217F71F5419D25E1031AFEE585313896444934EB04B903A685B1448B755D56F701AFE9BE2CE";
            ExpectedHashOfDefaultData = "154F99998573B5FC21E3DF86EE1E0161A6E0E912C4361088FE46D2E3543070EFE9746E326BC09E77EC06BCA60955538821C010411B4D0D6BF9BF2D2221CC8017";
            ExpectedHashOfOnetoNine   = "F5AB8BAFA6F2F72B431188AC38AE2DE7BB618FB3D38B6CBF639DEFCDD5E10A86B22FCCFF571DA37E42B23B80B657EE4D936478F582280A87D6DBB1DA73F5C47D";
            ExpectedHashOfabcde       = "F3E89A60EC4B0B1854744984E421D22B82F181BD4601FB9B1726B2662DA61C29DFF09E75814ACB2639FD79E56616E55FC135F8476F0302B3DC8D44E082EB83A8";
            ExpectedHashOfDefaultDataWithHMACWithLongKey  = "8E6F664622E2637AE477C00F314087FF8F6A8142D8CCF8946A451982AB750566DFD9BF97A50D705389FBF450525098797924DC443EFFDB1A1C945ECEA5DE9553";
            ExpectedHashOfDefaultDataWithHMACWithShortKey = "945EF4F96C681CC9C30A3EB1193FA13FD4ACD87D7C4A86D62AC9D8DCA74A32BB0DDC055EA75383A653E06B8E25266154DE5BE6B23C69723B795A1680EE844834";

            UnkeyedTestVectors = Blake2BTestVectors.UnkeyedBlake2B;
            KeyedTestVectors   = Blake2BTestVectors.KeyedBlake2B;
        }
示例#2
0
        public static byte[] ComputeHash(byte[] data, int start, int count, Blake2BConfig config)
        {
            var hasher = Create(config);

            hasher.Update(data, start, count);
            return(hasher.Finish());
        }
        public static void crypto_sign_keypair(byte[] pk, int pkoffset, byte[] sk, int skoffset, byte[] seed, int seedoffset)
        {
            GroupElementP3 A;
            int            i;

            Array.Copy(seed, seedoffset, sk, skoffset, 32);

            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(sk, skoffset, 32);
            byte[] h = hasher.Finish();
            //byte[] h = Sha512.Hash(sk, skoffset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);

            GroupOperations.ge_scalarmult_base(out A, h, 0);
            GroupOperations.ge_p3_tobytes(pk, pkoffset, ref A);

            for (i = 0; i < 32; ++i)
            {
                sk[skoffset + 32 + i] = pk[pkoffset + i];
            }
            CryptoBytes.Wipe(h);
        }
        public void Blake2BFactory_Create_Config_Works()
        {
            var blake2BConfig = new Blake2BConfig()
            {
                HashSizeInBits  = 256,
                Key             = new byte[64],
                Salt            = new byte[16],
                Personalization = new byte[16],
            };

            var blake2BFactory = Blake2BFactory.Instance;
            var blake2BHash    = blake2BFactory.Create(blake2BConfig);

            Assert.NotNull(blake2BHash);
            Assert.IsType <Blake2B_Implementation>(blake2BHash);


            var resultingBlake2BConfig = blake2BHash.Config;

            Assert.Equal(blake2BConfig.HashSizeInBits, resultingBlake2BConfig.HashSizeInBits);

            Assert.Equal(blake2BConfig.Key, resultingBlake2BConfig.Key);
            Assert.Equal(blake2BConfig.Salt, resultingBlake2BConfig.Salt);
            Assert.Equal(blake2BConfig.Personalization, resultingBlake2BConfig.Personalization);
        }
示例#5
0
文件: blake2b.cs 项目: shangqd/turtle
        public static byte[] GetHashByte(byte[] bs)
        {
            Blake2BConfig config = new Blake2BConfig();

            config.HashSizeInBits = 256;
            return(Blake2BFactory.Instance.Create(config).ComputeHash(bs).Hash.ToArray());
        }
示例#6
0
        public bool ValidateAddress(string address)
        {
            if (address.Length != 64 && !address.StartsWith("xrb_"))
            {
                return(false);
            }
            var pk32 = address.Substring(4, 52);
            var pk   = Base32withPadding.Decode(pk32, _base32Alphabet, 4);

            var checksum        = address.Substring(56);
            var checksumDecoded = Base32withPadding.Decode(checksum, _base32Alphabet, 0);

            checksumDecoded = checksumDecoded.Reverse().ToArray();

            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 5
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(pk);
            var pkChecksum = hasher.Finish();

            return(pkChecksum.SequenceEqual(checksumDecoded));
        }
        /// <summary>Blake2 hashed with bytes concated at the end.</summary>
        /// <param name="bytes">The bytes.</param>
        /// <param name="size">The size.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        public static byte[] Blake2Concat(byte[] bytes, int size = 128)
        {
            var config = new Blake2BConfig {
                OutputSizeInBits = size, Key = null
            };

            return(Blake2B.ComputeHash(bytes, config).Concat(bytes).ToArray());
        }
        /// <summary>Blake2 hashed the specified bytes.</summary>
        /// <param name="bytes">The bytes.</param>
        /// <param name="size">The size.</param>
        /// <param name="key">The key.</param>
        /// <returns>
        ///   <br />
        /// </returns>
        public static byte[] Blake2(byte[] bytes, int size = 128, IReadOnlyList <byte> key = null)
        {
            var config = new Blake2BConfig {
                OutputSizeInBits = size, Key = null
            };

            return(Blake2B.ComputeHash(bytes, config));
        }
示例#9
0
        public byte[] Blake2b(byte[] input)
        {
            var blakeConfig = new Blake2BConfig {
                OutputSizeInBits = 256
            };

            return(Blake2B.ComputeHash(input, 0, input.Count(), blakeConfig));
        }
示例#10
0
        public static byte[] FastHash(byte[] message, int offset, int length)
        {
            var blakeConfig = new Blake2BConfig {
                OutputSizeInBits = 256
            };

            return(Blake2B.ComputeHash(message, offset, length, blakeConfig));
        }
示例#11
0
            } // end function CreateBlake2XB

            public static IHash CreateBlake2XB(byte[] a_Key, UInt64 a_XofSizeInBits)
            {
                IBlake2BConfig config = new Blake2BConfig(64);

                config.Key = a_Key.DeepCopy();

                return(CreateBlake2XB(new Blake2XBConfig(config, null), a_XofSizeInBits));
            } // end function CreateBlake2XB
示例#12
0
        /// <summary>
        /// return hash
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] CalculateHash(byte[] data)
        {
            Blake2BConfig config = new Blake2BConfig();

            config.HashSizeInBits = 256;
            IBlake2B blake2B = Blake2BFactory.Instance.Create(config);

            return(blake2B.ComputeHash(data).Hash);
        }
示例#13
0
        public static byte[] SecureHash(byte[] message, int offset, int lenght)
        {
            var blakeConfig = new Blake2BConfig {
                OutputSizeInBits = 256
            };
            var blake2B = Blake2B.ComputeHash(message, offset, lenght, blakeConfig);

            return(Hash(blake2B, 0, blake2B.Length, Keccak256));
        }
示例#14
0
        private static byte[] CalculateBlake2StrongSum(byte[] block)
        {
            //IL_0001: Unknown result type (might be due to invalid IL or missing references)
            //IL_0006: Unknown result type (might be due to invalid IL or missing references)
            //IL_0013: Expected O, but got Unknown
            Blake2BConfig val = new Blake2BConfig();

            val.set_OutputSizeInBytes(32);
            return(Blake2B.ComputeHash(block, val));
        }
示例#15
0
        /// <summary>
        /// use UTF8 encode data and calculate hash
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] CalculateHash(string data)
        {
            Blake2BConfig config = new Blake2BConfig();

            config.HashSizeInBits = 256;
            IBlake2B blake2B = Blake2BFactory.Instance.Create(config);

            byte[] bytes = Encoding.UTF8.GetBytes(data);
            return(blake2B.ComputeHash(bytes).Hash);
        }
示例#16
0
        public void Blake2BConfig_Defaults_HaventChanged()
        {
            var blake2BConfig = new Blake2BConfig();

            Assert.Equal(512, blake2BConfig.HashSizeInBits);

            Assert.Null(blake2BConfig.Key);
            Assert.Null(blake2BConfig.Salt);
            Assert.Null(blake2BConfig.Personalization);
        }
示例#17
0
文件: blake2b.cs 项目: shangqd/turtle
        public static string GetHash(string hex)
        {
            byte[]        bs     = bbc_base32.HexStringToByte(hex);
            Blake2BConfig config = new Blake2BConfig();

            config.HashSizeInBits = 256;
            List <byte> list = Blake2BFactory.Instance.Create(config).ComputeHash(bs).Hash.ToList();

            list.Reverse();
            return(bbc_base32.ByteToHexString(list.ToArray()));
        }
示例#18
0
        static readonly byte[] personalization = new byte[] { 99, 107, 98, 45, 100, 101, 102, 97, 117, 108, 116, 45, 104, 97, 115, 104 }; // ckb-default-hash

        public static byte[] ComputeHash(byte[] data)
        {
            Blake2BConfig config = new Blake2BConfig
            {
                Personalization   = personalization,
                OutputSizeInBytes = 32
            };
            SecureArrayCall secureArrayCall = default;

            return(Blake2B.ComputeHash(data, config, secureArrayCall));
        }
        public void Hash(Blake2BConfig config, byte[] message)
        {
            var hasher = Blake2B.Create(new Blake2BConfig()
            {
                OutputSizeInBytes = 64
            });

            hasher.Init();
            hasher.Update(Previous.ToByteArray());
            hasher.Update(Source.ToByteArray());
        }
示例#20
0
        public void Hash(Blake2BConfig config, byte[] message)
        {
            var hasher = Blake2B.Create(new Blake2BConfig()
            {
                OutputSizeInBytes = 64
            });

            hasher.Init();
            hasher.Update(Source.ToByteArray());
            hasher.Update(Representative.ToByteArray());
            hasher.Update(Account.ToByteArray());
        }
示例#21
0
        // Original crypto_sign_open, for reference only

        /*public static int crypto_sign_open(
         * byte[] m, out int mlen,
         * byte[] sm, int smlen,
         * byte[] pk)
         * {
         *  byte[] h = new byte[64];
         *  byte[] checkr = new byte[32];
         *  GroupElementP3 A;
         *  GroupElementP2 R;
         *  int i;
         *
         *  mlen = -1;
         *  if (smlen < 64) return -1;
         *  if ((sm[63] & 224) != 0) return -1;
         *  if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, 0) != 0) return -1;
         *
         *  for (i = 0; i < smlen; ++i) m[i] = sm[i];
         *  for (i = 0; i < 32; ++i) m[32 + i] = pk[i];
         *  Sha512BclWrapper.crypto_hash_sha512(h, m, 0, smlen);
         *  ScalarOperations.sc_reduce(h);
         *
         *  var sm32 = new byte[32];
         *  Array.Copy(sm, 32, sm32, 0, 32);
         *  GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
         *  GroupOperations.ge_tobytes(checkr, 0, ref R);
         *  if (Helpers.crypto_verify_32(checkr, sm) != 0)
         *  {
         *      for (i = 0; i < smlen; ++i)
         *          m[i] = 0;
         *      return -1;
         *  }
         *
         *  for (i = 0; i < smlen - 64; ++i)
         *      m[i] = sm[64 + i];
         *  for (i = smlen - 64; i < smlen; ++i)
         *      m[i] = 0;
         *  mlen = smlen - 64;
         *  return 0;
         * }*/

        public static bool crypto_sign_verify(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] pk, int pkoffset)
        {
            byte[]         h;
            byte[]         checkr = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((sig[sigoffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, pkoffset) != 0)
            {
                return(false);
            }

            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(sig, sigoffset, 32);
            hasher.Update(pk, pkoffset, 32);
            hasher.Update(m, moffset, mlen);
            h = hasher.Finish();

            /*
             * var hasher = new Sha512();
             * hasher.Update(sig, sigoffset, 32);
             * hasher.Update(pk, pkoffset, 32);
             * hasher.Update(m, moffset, mlen);
             * h = hasher.Finish();
             */

            ScalarOperations.sc_reduce(h);

            var sm32 = new byte[32];//todo: remove allocation

            Array.Copy(sig, sigoffset + 32, sm32, 0, 32);
            GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
            GroupOperations.ge_tobytes(checkr, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, 0, sig, sigoffset, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checkr);
            return(result);
        }
示例#22
0
        byte[] GenerateRaiAddressSeed(int index)
        {
            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 32
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(Seed);
            var indexBytes = BitConverter.GetBytes(index).Reverse().ToArray();

            hasher.Update(indexBytes);
            return(hasher.Finish());
        }
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(privateKey.Array, privateKey.Offset, 32);
            byte[] h = hasher.Finish();
            //byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
        /// <summary>
        /// Does a Blake2 hash with the ability to truncate or extend the hash to any length.
        /// </summary>
        /// <param name="hash">
        /// The buffer to fill with the hash.
        /// </param>
        /// <param name="inputBuffer">
        /// What to hash.
        /// </param>
        /// <param name="secureArrayCall">
        /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
        /// </param>
        private static void Blake2BLong(byte[] hash, byte[] inputBuffer, SecureArrayCall secureArrayCall)
        {
            var outputLengthBytes = new byte[4];

            using var intermediateHash = SecureArray <byte> .Best(Blake2B.OutputLength, secureArrayCall);

            var config = new Blake2BConfig
            {
                Result64ByteBuffer = intermediateHash.Buffer,
                OutputSizeInBytes  = hash.Length > 64 ? 64 : hash.Length,
            };

            Store32(outputLengthBytes, hash.Length);
            using (var blakeHash = Blake2B.Create(config, secureArrayCall))
            {
                blakeHash.Update(outputLengthBytes);
                blakeHash.Update(inputBuffer);
                blakeHash.Finish();
            }

            if (hash.Length <= intermediateHash.Buffer.Length)
            {
                Array.Copy(intermediateHash.Buffer, hash, hash.Length);
                return;
            }

            const int b2B2 = Blake2B.OutputLength / 2;

            Array.Copy(intermediateHash.Buffer, hash, b2B2);
            int pos           = b2B2;
            int lastHashIndex = hash.Length - Blake2B.OutputLength;
            var toHash        = new byte[Blake2B.OutputLength];

            while (pos < lastHashIndex)
            {
                Array.Copy(intermediateHash.Buffer, toHash, intermediateHash.Buffer.Length);
                Blake2B.ComputeHash(toHash, config, secureArrayCall);
                Array.Copy(intermediateHash.Buffer, 0, hash, pos, b2B2);
                pos += b2B2;
            }

            Array.Copy(intermediateHash.Buffer, toHash, intermediateHash.Buffer.Length);
            Blake2B.ComputeHash(toHash, config, secureArrayCall);
            Array.Copy(intermediateHash.Buffer, 0, hash, pos, hash.Length - pos);
        }
示例#25
0
        private Blake2B Blake2BPCreateRoot()
        {
            IBlake2BConfig blake2BConfig = new Blake2BConfig(HashSize);

            blake2BConfig.Key = Key.DeepCopy();

            IBlake2BTreeConfig blake2BTreeConfig = new Blake2BTreeConfig();

            blake2BTreeConfig.FanOut        = (byte)ParallelismDegree;
            blake2BTreeConfig.MaxDepth      = 2;
            blake2BTreeConfig.NodeDepth     = 1;
            blake2BTreeConfig.LeafSize      = 0;
            blake2BTreeConfig.NodeOffset    = 0;
            blake2BTreeConfig.InnerHashSize = (byte)OutSizeInBytes;
            blake2BTreeConfig.IsLastNode    = true;

            return(new Blake2B(blake2BConfig, blake2BTreeConfig, false));
        }
示例#26
0
        public void Blake2BConfig_Clone_WithNullArrays_Works()
        {
            var blake2BConfig = new Blake2BConfig()
            {
                Key             = null,
                Salt            = null,
                Personalization = null,
            };


            var blake2BConfigClone = blake2BConfig.Clone();

            Assert.IsType <Blake2BConfig>(blake2BConfigClone);

            Assert.Null(blake2BConfigClone.Key);
            Assert.Null(blake2BConfigClone.Salt);
            Assert.Null(blake2BConfigClone.Personalization);
        }
示例#27
0
        public void Init(byte[] key, byte[] salt, byte[] tag)
        {
            byte[] keyBytes = null, saltBytes = null, tagBytes = null;

            if (key != null)
            {
                if (key.Length > 128)
                {
                    throw new ArgumentOutOfRangeException("key", "Key is longer than 128 bytes.");
                }
                keyBytes = new byte[128];
                Array.Copy(key, keyBytes, key.Length);
            }

            if (salt != null)
            {
                if (salt.Length > 16)
                {
                    throw new ArgumentOutOfRangeException("salt", "Salt is longer than 16 bytes.");
                }
                saltBytes = new byte[16];
                Array.Copy(salt, saltBytes, salt.Length);
            }

            if (tag != null)
            {
                if (tag.Length > 16)
                {
                    throw new ArgumentOutOfRangeException("tag", "Tag is longer than 16 bytes.");
                }
                tagBytes = new byte[16];
                Array.Copy(tag, tagBytes, tag.Length);
            }

            var config = new Blake2BConfig()
            {
                Key               = keyBytes,
                Salt              = saltBytes,
                Personalization   = tagBytes,
                OutputSizeInBytes = outputSize,
            };

            hasher = new Blake2BHasher(config);
        }
示例#28
0
        public string PublicAddress(int index = 0)
        {
            var addressSeed = GenerateRaiAddressSeed(index);

            var pk   = Ed25519.PublicKeyFromSeed(addressSeed);
            var pk32 = Base32withPadding.Encode(pk, _base32Alphabet, 260);

            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 5
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(pk);
            var checksum   = hasher.Finish().Reverse().ToArray();
            var checksum32 = Base32withPadding.Encode(checksum, _base32Alphabet, 40);

            return($"xrb_{pk32}{checksum32}");
        }
示例#29
0
        /*public static void crypto_sign(
         * byte[] sm, out int smlen,
         * byte[] m, int mlen,
         * byte[] sk
         * )
         * {
         *      byte[] az = new byte[64];
         *      byte[] r = new byte[64];
         *      byte[] hram = new byte[64];
         *      GroupElementP3 R;
         *      int i;
         *
         *      Helpers.crypto_hash_sha512(az, sk, 0, 32);
         *      az[0] &= 248;
         *      az[31] &= 63;
         *      az[31] |= 64;
         *
         *      smlen = mlen + 64;
         *      for (i = 0; i < mlen; ++i) sm[64 + i] = m[i];
         *      for (i = 0; i < 32; ++i) sm[32 + i] = az[32 + i];
         *      Helpers.crypto_hash_sha512(r, sm, 32, mlen + 32);
         *      for (i = 0; i < 32; ++i) sm[32 + i] = sk[32 + i];
         *
         *      ScalarOperations.sc_reduce(r);
         *      GroupOperations.ge_scalarmult_base(out R, r, 0);
         *      GroupOperations.ge_p3_tobytes(sm, 0, ref R);
         *
         *      Helpers.crypto_hash_sha512(hram, sm, 0, mlen + 64);
         *      ScalarOperations.sc_reduce(hram);
         *      var sm32 = new byte[32];
         *      Array.Copy(sm, 32, sm32, 0, 32);
         *      ScalarOperations.sc_muladd(sm32, hram, az, r);
         *      Array.Copy(sm32, 0, sm, 32, 32);
         * }*/

        public static void crypto_sign2(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] sk, int skoffset)
        {
            byte[]         az;
            byte[]         r;
            byte[]         hram;
            GroupElementP3 R;
            var            blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);
            //var hasher = new Sha512();
            {
                hasher.Update(sk, skoffset, 32);
                az = hasher.Finish();
                ScalarOperations.sc_clamp(az, 0);

                hasher.Init();
                hasher.Update(az, 32, 32);
                hasher.Update(m, moffset, mlen);
                r = hasher.Finish();

                ScalarOperations.sc_reduce(r);
                GroupOperations.ge_scalarmult_base(out R, r, 0);
                GroupOperations.ge_p3_tobytes(sig, sigoffset, ref R);

                hasher.Init();
                hasher.Update(sig, sigoffset, 32);
                hasher.Update(sk, skoffset + 32, 32);
                hasher.Update(m, moffset, mlen);
                hram = hasher.Finish();

                ScalarOperations.sc_reduce(hram);
                var s = new byte[32];                //todo: remove allocation
                Array.Copy(sig, sigoffset + 32, s, 0, 32);
                ScalarOperations.sc_muladd(s, hram, az, r);
                Array.Copy(s, 0, sig, sigoffset + 32, 32);
                CryptoBytes.Wipe(s);
            }
        }
        public void Blake2BFactory_Create_Works()
        {
            var defaultBlake2BConfig = new Blake2BConfig();

            var blake2BFactory = Blake2BFactory.Instance;
            var blake2BHash    = blake2BFactory.Create();

            Assert.NotNull(blake2BHash);
            Assert.IsType <Blake2B_Implementation>(blake2BHash);


            var resultingBlake2BConfig = blake2BHash.Config;

            Assert.Equal(defaultBlake2BConfig.HashSizeInBits, resultingBlake2BConfig.HashSizeInBits);

            Assert.Equal(defaultBlake2BConfig.Key, resultingBlake2BConfig.Key);
            Assert.Equal(defaultBlake2BConfig.Salt, resultingBlake2BConfig.Salt);
            Assert.Equal(defaultBlake2BConfig.Personalization, resultingBlake2BConfig.Personalization);
        }