/**
* Novacoin classes library
* Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
using System;
using System.IO;
using System.Security.Cryptography;
namespace Novacoin
{
public class CryptoUtils
{
private static SHA1Managed _sha1 = new SHA1Managed();
private static SHA256Managed _sha256 = new SHA256Managed();
private static RIPEMD160Managed _ripe160 = new RIPEMD160Managed();
///
/// Sha1 calculation
///
/// Bytes to hash
/// Hashing result
public static byte[] ComputeSha1(byte[] inputBytes)
{
return _sha1.ComputeHash(inputBytes, 0, inputBytes.Length);
}
///
/// Sha256 calculation
///
/// Bytes to hash
/// Hashing result
public static byte[] ComputeSha256(byte[] inputBytes)
{
return _sha256.ComputeHash(inputBytes, 0, inputBytes.Length);
}
///
/// RIPEMD-160 calculation
///
/// Bytes to hash
/// Hashing result
public static byte[] ComputeRipeMD160(byte[] inputBytes)
{
return _ripe160.ComputeHash(inputBytes, 0, inputBytes.Length);
}
///
/// RipeMD160(Sha256(X)) calculation
///
/// Bytes to hash
/// Hashing result
public static byte[] ComputeHash160(byte[] inputBytes)
{
var digest1 = _sha256.ComputeHash(inputBytes, 0, inputBytes.Length);
return _ripe160.ComputeHash(digest1, 0, digest1.Length);
}
///
/// Sha256(Sha256(X)) calculation
///
/// Bytes to hash
/// Hashing result
public static byte[] ComputeHash256(byte[] dataBytes)
{
var digest1 = _sha256.ComputeHash(dataBytes, 0, dataBytes.Length);
return _sha256.ComputeHash(digest1, 0, digest1.Length);
}
///
/// Sha256(Sha256(X)) calculation
///
/// Reference to first half of data
/// Reference to second half of data
/// Hashing result
public static byte[] ComputeHash256(ref byte[] input1, ref byte[] input2)
{
var buffer = new byte[64];
input1.CopyTo(buffer, 0);
input2.CopyTo(buffer, input1.Length);
var digest1 = _sha256.ComputeHash(buffer, 0, buffer.Length);
return _sha256.ComputeHash(digest1, 0, digest1.Length);
}
public static byte[] PBKDF2_Sha256(int dklen, byte[] password, byte[] salt, int iterationCount)
{
/* Init HMAC state. */
using (var hmac = new HMACSHA256(password))
{
int hashLength = hmac.HashSize / 8;
if ((hmac.HashSize & 7) != 0)
{
hashLength++;
}
int keyLength = dklen / hashLength;
if (dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
{
throw new ArgumentOutOfRangeException("dklen");
}
if (dklen % hashLength != 0)
{
keyLength++;
}
var extendedkey = new byte[salt.Length + 4];
Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
using (var ms = new MemoryStream())
{
/* Iterate through the blocks. */
for (int i = 0; i < keyLength; i++)
{
/* Generate INT(i + 1). */
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);
/* Compute U_1 = PRF(P, S || INT(i)). */
var u = hmac.ComputeHash(extendedkey);
Array.Clear(extendedkey, salt.Length, 4);
/* T_i = U_1 ... */
var f = u;
for (int j = 1; j < iterationCount; j++)
{
/* Compute U_j. */
u = hmac.ComputeHash(u);
for (int k = 0; k < f.Length; k++)
{
/* ... xor U_j ... */
f[k] ^= u[k];
}
}
/* Copy as many bytes as necessary into memory stream. */
ms.Write(f, 0, f.Length);
Array.Clear(u, 0, u.Length);
Array.Clear(f, 0, f.Length);
}
ms.Position = 0;
/* Initialize result array. */
var dk = new byte[dklen];
/* Read key from memory stream. */
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;
}
}
}
}
}