19 using System.Security.Cryptography;
22 namespace Deveel.Data.Security {
26 private const int DefaultIterationCount = 10000;
29 return MakePbkdf2String(hash, input, salt, length, DefaultIterationCount);
33 return hash.MakePbkdf2String(input, Convert.FromBase64String(salt), length, iterationCount);
37 return MakePbkdf2String(hash, input, salt, length, DefaultIterationCount);
41 var data = Encoding.UTF8.GetBytes(input);
42 var result = hash.MakePbkdf2(data, salt, length, iterationCount);
43 return Convert.ToBase64String(result);
47 var hashKey = hash.
Key;
48 if (hashKey == null || hashKey.Length == 0)
49 throw new InvalidOperationException(
"Key was not specified for the hash.");
51 return MakePbkdf2(hash, hashKey, salt, length, iterationCount);
55 return MakePbkdf2(hash, data, salt, length, DefaultIterationCount);
65 int keyLength = length/hashLength;
66 if (length > (0xFFFFFFFFL*hashLength) || length < 0)
67 throw new ArgumentOutOfRangeException(
"length");
69 if (length%hashLength != 0)
72 byte[] extendedkey =
new byte[salt.Length + 4];
73 Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
75 using (var ms =
new MemoryStream()) {
76 for (
int i = 0; i < keyLength; i++) {
77 extendedkey[salt.Length] = (byte) (((i + 1) >> 24) & 0xFF);
78 extendedkey[salt.Length + 1] = (byte) (((i + 1) >> 16) & 0xFF);
79 extendedkey[salt.Length + 2] = (byte) (((i + 1) >> 8) & 0xFF);
80 extendedkey[salt.Length + 3] = (byte) (((i + 1)) & 0xFF);
82 byte[] u = hash.
Compute(extendedkey);
83 Array.Clear(extendedkey, salt.Length, 4);
86 for (
int j = 1; j < iterationCount; j++) {
88 for (
int k = 0; k < f.Length; k++) {
93 ms.Write(f, 0, f.Length);
94 Array.Clear(u, 0, u.Length);
95 Array.Clear(f, 0, f.Length);
98 byte[] dk =
new byte[length];
100 ms.Read(dk, 0, length);
103 for (
long i = 0; i < ms.Length; i++) {
107 Array.Clear(extendedkey, 0, extendedkey.Length);
113 return VerifyPbkdf2(hash, hashed, otherData, salt, DefaultIterationCount);
117 int length = hashed.Length;
119 var otherHashed = hash.MakePbkdf2(otherData, salt, length, iterationCount);
121 if (otherHashed.Length != hashed.Length)
124 return ByteArraysEqual(hashed, otherHashed);
128 return VerifyPbkdf2String(hash, hashedString, otherString, salt, DefaultIterationCount);
132 return hash.VerifyPbkdf2String(hashedString, otherString, Convert.ToBase64String(salt), iterationCount);
136 return VerifyPbkdf2String(hash, hashedString, otherString, saltString, DefaultIterationCount);
140 var hashed = Convert.FromBase64String(hashedString);
141 var otherData = Encoding.UTF8.GetBytes(otherString);
142 var salt = Convert.FromBase64String(saltString);
144 return hash.VerifyPbkdf2(hashed, otherData, salt, iterationCount);
148 if (ReferenceEquals(a, b)) {
152 if (a == null || b == null || a.Length != b.Length) {
157 for (
int i = 0; i < a.Length; i++) {
158 areSame &= (a[i] == b[i]);
166 var data = Encoding.UTF8.GetBytes(s);
167 return BinaryToHex(hash.
Compute(data));
171 int byteLength = (hash.
HashSize / 2) / 8;
172 byte[] buf =
new byte[byteLength];
173 var rng =
new RNGCryptoServiceProvider();
179 return Convert.ToBase64String(hash.GenerateSalt());
183 char[] hex =
new char[data.Length * 2];
185 for (
int iter = 0; iter < data.Length; iter++) {
186 byte hexChar = ((byte)(data[iter] >> 4));
187 hex[iter * 2] = (char)(hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
188 hexChar = ((byte)(data[iter] & 0xF));
189 hex[(iter * 2) + 1] = (
char)(hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
191 return new string(hex);
static byte[] MakePbkdf2(this IKeyedHashFunction hash, byte[] salt, int length, int iterationCount)
static string MakePbkdf2String(this IKeyedHashFunction hash, string input, string salt, int length)
static string MakePbkdf2String(this IKeyedHashFunction hash, string input, byte[] salt, int length, int iterationCount)
static bool VerifyPbkdf2String(this IKeyedHashFunction hash, string hashedString, string otherString, byte[] salt)
int HashSize
Gets the size of the hash to generate.
static bool ByteArraysEqual(byte[] a, byte[] b)
static string ComputeString(this IHashFunction hash, string s)
static string MakePbkdf2String(this IKeyedHashFunction hash, string input, string salt, int length, int iterationCount)
static bool VerifyPbkdf2String(this IKeyedHashFunction hash, string hashedString, string otherString, string saltString)
Defines a function to hash as user provided password
static byte[] MakePbkdf2(this IKeyedHashFunction hash, byte[] data, byte[] salt, int length, int iterationCount)
static byte[] MakePbkdf2(this IKeyedHashFunction hash, byte[] data, byte[] salt, int length)
static string BinaryToHex(byte[] data)
static string GenerateSaltString(this IHashFunction hash)
static bool VerifyPbkdf2String(this IKeyedHashFunction hash, string hashedString, string otherString, string saltString, int iterationCount)
static bool VerifyPbkdf2String(this IKeyedHashFunction hash, string hashedString, string otherString, byte[] salt, int iterationCount)
An hash function that requires a private key to compute the final result.
static bool VerifyPbkdf2(this IKeyedHashFunction hash, byte[] hashed, byte[] otherData, byte[] salt)
byte[] Key
Gets or sets the private key to use for computing the hash.
static byte[] GenerateSalt(this IHashFunction hash)
byte[] Compute(byte[] data)
Computes the hash from the given input.
static bool VerifyPbkdf2(this IKeyedHashFunction hash, byte[] hashed, byte[] otherData, byte[] salt, int iterationCount)
static string MakePbkdf2String(this IKeyedHashFunction hash, string input, byte[] salt, int length)