mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-13 05:25:00 +00:00
120 lines
3.6 KiB
C#
120 lines
3.6 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto;
|
|
using Org.BouncyCastle.Crypto.Digests;
|
|
using Org.BouncyCastle.Crypto.Macs;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
|
|
namespace SharpCompress.Crypto
|
|
{
|
|
//Gathered from:
|
|
//http://stackoverflow.com/questions/3210795/pbkdf2-in-bouncy-castle-c-sharp and Rfc2898DeriveBytes
|
|
internal class PBKDF2
|
|
{
|
|
private readonly IMac hMac = new HMac(new Sha1Digest());
|
|
private readonly byte[] state = new byte[20];
|
|
private int endIndex;
|
|
private int startIndex;
|
|
private uint block = 1u;
|
|
private readonly byte[] password;
|
|
private readonly byte[] salt;
|
|
private readonly int iterations;
|
|
|
|
|
|
public PBKDF2(byte[] password, byte[] salt, int iterations)
|
|
{
|
|
this.password = password;
|
|
this.salt = salt;
|
|
this.iterations = iterations;
|
|
}
|
|
|
|
public byte[] GetBytes(int cb)
|
|
{
|
|
if (cb <= 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("cb");
|
|
}
|
|
byte[] array = new byte[cb];
|
|
int i = 0;
|
|
int num = endIndex - startIndex;
|
|
if (num > 0)
|
|
{
|
|
if (cb < num)
|
|
{
|
|
Buffer.BlockCopy(state, startIndex, array, 0, cb);
|
|
startIndex += cb;
|
|
return array;
|
|
}
|
|
Buffer.BlockCopy(state, startIndex, array, 0, num);
|
|
startIndex = (endIndex = 0);
|
|
i += num;
|
|
}
|
|
while (i < cb)
|
|
{
|
|
byte[] src = Hash();
|
|
int num2 = cb - i;
|
|
if (num2 <= 20)
|
|
{
|
|
Buffer.BlockCopy(src, 0, array, i, num2);
|
|
i += num2;
|
|
Buffer.BlockCopy(src, num2, state, startIndex, 20 - num2);
|
|
endIndex += 20 - num2;
|
|
return array;
|
|
}
|
|
Buffer.BlockCopy(src, 0, array, i, 20);
|
|
i += 20;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
private byte[] Hash()
|
|
{
|
|
byte[] array = UIntToOctet(block);
|
|
ICipherParameters param = new KeyParameter(password);
|
|
|
|
hMac.Init(param);
|
|
hMac.BlockUpdate(salt, 0, salt.Length);
|
|
|
|
hMac.BlockUpdate(array, 0, array.Length);
|
|
byte[] array2 = new byte[20];
|
|
hMac.DoFinal(array2, 0);
|
|
|
|
hMac.Init(param);
|
|
|
|
byte[] array3 = new byte[20];
|
|
Buffer.BlockCopy(array2, 0, array3, 0, 20);
|
|
int num = 2;
|
|
while (num <= (long)((ulong)iterations))
|
|
{
|
|
hMac.BlockUpdate(array2, 0, array2.Length);
|
|
hMac.DoFinal(array2, 0);
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
array3[i] ^= array2[i];
|
|
}
|
|
num++;
|
|
}
|
|
block += 1u;
|
|
return array3;
|
|
}
|
|
|
|
internal static byte[] UIntToOctet(uint i)
|
|
{
|
|
byte[] bytes = BitConverter.GetBytes(i);
|
|
byte[] result = new[]
|
|
{
|
|
bytes[3],
|
|
bytes[2],
|
|
bytes[1],
|
|
bytes[0]
|
|
};
|
|
if (!BitConverter.IsLittleEndian)
|
|
{
|
|
return bytes;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|
|
}
|
|
|