Nic*_*ick 22 c# pbkdf2 rfc2898
伙计们,我正在尝试在C#中实现一个创建WPA共享密钥的PBKDF2函数.我在这里找到了一些:http://msdn.microsoft.com/en-us/magazine/cc163913.aspx似乎产生了一个有效的结果,但是它的一个字节太短......而且错误的PSK值.
为了测试输出,我将其与此进行比较:http://www.xs4all.nl/~rjoris/wpapsk.html或http://anandam.name/pbkdf2/
我确实找到了一种方法来使用C#内置库来调用Rfc2898DeriveBytes.使用这个,我得到一个有效的输出:
Rfc2898DeriveBytes k3 = new Rfc2898DeriveBytes(pwd1, salt1, 4096);
byte[] answers = k3.GetBytes(32);
Run Code Online (Sandbox Code Playgroud)
现在,我使用Rfc2898DeriveBytes的一个限制是"盐"必须是8个八位字节长.如果它更短,则Rfc2898DeriveBytes会抛出异常.我想我所要做的就是将盐(如果它更短)填充到8个字节,我会很好.但不是!我已经尝试了几乎所有填充与较短盐的组合,但我不能复制我从上面这两个网站得到的结果.
那么底线是,这是否意味着Rfc2898DeriveBytes只是不能使用短于8个字节的源盐?如果是这样,有没有人知道我可以使用哪些C#代码为WPA预共享密钥实现PBKDF2?
Dod*_*bit 15
这是一个不需要8字节盐的实现.
您可以按如下方式计算WPA密钥:
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(passphrase, Encoding.UTF8.GetBytes(name), 4096);
key = rfc2898.GetBytes(32);
public class Rfc2898DeriveBytes : DeriveBytes
{
const int BlockSize = 20;
uint block;
byte[] buffer;
int endIndex;
readonly HMACSHA1 hmacsha1;
uint iterations;
byte[] salt;
int startIndex;
public Rfc2898DeriveBytes(string password, int saltSize)
: this(password, saltSize, 1000)
{
}
public Rfc2898DeriveBytes(string password, byte[] salt)
: this(password, salt, 1000)
{
}
public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
{
if (saltSize < 0)
{
throw new ArgumentOutOfRangeException("saltSize");
}
byte[] data = new byte[saltSize];
new RNGCryptoServiceProvider().GetBytes(data);
Salt = data;
IterationCount = iterations;
hmacsha1 = new HMACSHA1(new UTF8Encoding(false).GetBytes(password));
Initialize();
}
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations) : this(new UTF8Encoding(false).GetBytes(password), salt, iterations)
{
}
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations)
{
Salt = salt;
IterationCount = iterations;
hmacsha1 = new HMACSHA1(password);
Initialize();
}
static byte[] Int(uint i)
{
byte[] bytes = BitConverter.GetBytes(i);
byte[] buffer2 = new byte[] {bytes[3], bytes[2], bytes[1], bytes[0]};
if (!BitConverter.IsLittleEndian)
{
return bytes;
}
return buffer2;
}
byte[] DeriveKey()
{
byte[] inputBuffer = Int(block);
hmacsha1.TransformBlock(salt, 0, salt.Length, salt, 0);
hmacsha1.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
byte[] hash = hmacsha1.Hash;
hmacsha1.Initialize();
byte[] buffer3 = hash;
for (int i = 2; i <= iterations; i++)
{
hash = hmacsha1.ComputeHash(hash);
for (int j = 0; j < BlockSize; j++)
{
buffer3[j] = (byte) (buffer3[j] ^ hash[j]);
}
}
block++;
return buffer3;
}
public override byte[] GetBytes(int bytesToGet)
{
if (bytesToGet <= 0)
{
throw new ArgumentOutOfRangeException("bytesToGet");
}
byte[] dst = new byte[bytesToGet];
int dstOffset = 0;
int count = endIndex - startIndex;
if (count > 0)
{
if (bytesToGet < count)
{
Buffer.BlockCopy(buffer, startIndex, dst, 0, bytesToGet);
startIndex += bytesToGet;
return dst;
}
Buffer.BlockCopy(buffer, startIndex, dst, 0, count);
startIndex = endIndex = 0;
dstOffset += count;
}
while (dstOffset < bytesToGet)
{
byte[] src = DeriveKey();
int num3 = bytesToGet - dstOffset;
if (num3 > BlockSize)
{
Buffer.BlockCopy(src, 0, dst, dstOffset, BlockSize);
dstOffset += BlockSize;
}
else
{
Buffer.BlockCopy(src, 0, dst, dstOffset, num3);
dstOffset += num3;
Buffer.BlockCopy(src, num3, buffer, startIndex, BlockSize - num3);
endIndex += BlockSize - num3;
return dst;
}
}
return dst;
}
void Initialize()
{
if (buffer != null)
{
Array.Clear(buffer, 0, buffer.Length);
}
buffer = new byte[BlockSize];
block = 1;
startIndex = endIndex = 0;
}
public override void Reset()
{
Initialize();
}
public int IterationCount
{
get
{
return (int) iterations;
}
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException("value");
}
iterations = (uint) value;
Initialize();
}
}
public byte[] Salt
{
get
{
return (byte[]) salt.Clone();
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
salt = (byte[]) value.Clone();
Initialize();
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
查看Microsoft链接,我做了一些更改,以使PMK与您提出的链接中发现的PMK相同.
将SHA算法从SHA256Managed更改为SHA1Managed,用于内部和外部哈希.
将HASH_SIZE_IN_BYTES更改为等于20而不是34.
这会生成正确的WPA密钥.
我知道这有点晚了,但我刚刚开始寻找这种信息,并认为我可以帮助其他人.如果有人读过这篇文章,关于PRF功能的任何想法以及如何在C#中做到这一点?
| 归档时间: |
|
| 查看次数: |
15028 次 |
| 最近记录: |