Files
Intellix/Intelix.Helper.Hashing/PBKDF2.cs
T
2026-08-27 10:55:23 -06:00

107 lines
2.5 KiB
C#

using System;
using System.Security.Cryptography;
namespace Intelix.Helper.Hashing;
public class PBKDF2
{
private readonly int _blockSize;
private uint _blockIndex = 1u;
private byte[] _bufferBytes;
private int _bufferStartIndex;
private int _bufferEndIndex;
private HMAC Algorithm { get; }
private byte[] Salt { get; }
private int IterationCount { get; }
public PBKDF2(HMAC algorithm, byte[] password, byte[] salt, int iterations)
{
Algorithm = algorithm ?? throw new ArgumentNullException("algorithm", "Algorithm cannot be null.");
Algorithm.Key = password ?? throw new ArgumentNullException("password", "Password cannot be null.");
Salt = salt ?? throw new ArgumentNullException("salt", "Salt cannot be null.");
IterationCount = iterations;
_blockSize = Algorithm.HashSize / 8;
_bufferBytes = new byte[_blockSize];
}
public byte[] GetBytes(int count)
{
byte[] array = new byte[count];
int i = 0;
int num = _bufferEndIndex - _bufferStartIndex;
if (num > 0)
{
if (count < num)
{
Buffer.BlockCopy(_bufferBytes, _bufferStartIndex, array, 0, count);
_bufferStartIndex += count;
return array;
}
Buffer.BlockCopy(_bufferBytes, _bufferStartIndex, array, 0, num);
_bufferStartIndex = (_bufferEndIndex = 0);
i += num;
}
for (; i < count; i += _blockSize)
{
int num2 = count - i;
_bufferBytes = Func();
if (num2 > _blockSize)
{
Buffer.BlockCopy(_bufferBytes, 0, array, i, _blockSize);
continue;
}
Buffer.BlockCopy(_bufferBytes, 0, array, i, num2);
_bufferStartIndex = num2;
_bufferEndIndex = _blockSize;
return array;
}
return array;
}
private byte[] Func()
{
byte[] array = new byte[Salt.Length + 4];
Buffer.BlockCopy(Salt, 0, array, 0, Salt.Length);
Buffer.BlockCopy(GetBytesFromInt(_blockIndex), 0, array, Salt.Length, 4);
byte[] array2 = Algorithm.ComputeHash(array);
byte[] array3 = array2;
for (int i = 2; i <= IterationCount; i++)
{
array2 = Algorithm.ComputeHash(array2, 0, array2.Length);
for (int j = 0; j < _blockSize; j++)
{
array3[j] ^= array2[j];
}
}
if (_blockIndex == uint.MaxValue)
{
throw new InvalidOperationException("Derived key too long.");
}
_blockIndex++;
return array3;
}
private static byte[] GetBytesFromInt(uint i)
{
byte[] bytes = BitConverter.GetBytes(i);
if (!BitConverter.IsLittleEndian)
{
return bytes;
}
return new byte[4]
{
bytes[3],
bytes[2],
bytes[1],
bytes[0]
};
}
}