我看到了一些像
这样的代码string password = "11111111";
byte[] salt = Encoding.ASCII.GetBytes("22222222");
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt);
RijndaelAlg.Key = key.GetBytes(RijndaelAlg.KeySize / 8);
我可以看到密钥是由Rfc2898DeriveBytes使用密码和盐生成的。然后AES通过GetBytes检索密钥。
但问题是,RFC2898DeriveBytes做了什么以及key.GetBytes(cb)做了什么?任何人都可以详细说明吗?我无法从文档中获得它。
答案 0 :(得分:12)
RFC2898是指2000年9月发布的基于密码的加密规范。实际上,Rfc2898DeriveBytes
需要密码和盐来生成密钥。它使用的方法称为PBKDF2(基于密码的密钥派生函数#2),并在RFC2898的5.2节中定义。从第5.2节开始:
PBKDF2应用伪随机函数(例如,参见附录B.1)来导出密钥。派生密钥的长度基本上是无限的。 (但是,派生密钥的最大有效搜索空间可能受底层伪随机函数的结构限制。有关进一步讨论,请参阅附录B.1。)建议将PBKDF2用于新应用程序。
有关详细信息,请参阅RFC2898。
至于Rfc2898DeriveBytes.GetBytes
的作用,它会在每次调用时返回不同的键;它实际上只是使用相同的密码和盐重复应用PBKDF2,但也是迭代计数。
这在RFC doc中概述,其中PBKDF2定义为
PBKDF2 (P, S, c, dkLen)
其中P
是密码,S
是盐,c
是迭代计数,dkLen
是所需密钥的长度。
答案 1 :(得分:5)
从反射器中查看实现:
public Rfc2898DeriveBytes(string password, byte[] salt) : this(password, salt, 0x3e8)
{
}
public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
{
if (saltSize < 0)
{
throw new ArgumentOutOfRangeException("saltSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
byte[] data = new byte[saltSize];
Utils.StaticRandomNumberGenerator.GetBytes(data);
this.Salt = data;
this.IterationCount = iterations;
this.m_hmacsha1 = new HMACSHA1(new UTF8Encoding(false).GetBytes(password));
this.Initialize();
}
public override byte[] GetBytes(int cb)
{
if (cb <= 0)
{
throw new ArgumentOutOfRangeException("cb", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
byte[] dst = new byte[cb];
int dstOffset = 0;
int count = this.m_endIndex - this.m_startIndex;
if (count > 0)
{
if (cb < count)
{
Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, cb);
this.m_startIndex += cb;
return dst;
}
Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, count);
this.m_startIndex = this.m_endIndex = 0;
dstOffset += count;
}
while (dstOffset < cb)
{
byte[] src = this.Func();
int num3 = cb - dstOffset;
if (num3 > 20)
{
Buffer.InternalBlockCopy(src, 0, dst, dstOffset, 20);
dstOffset += 20;
}
else
{
Buffer.InternalBlockCopy(src, 0, dst, dstOffset, num3);
dstOffset += num3;
Buffer.InternalBlockCopy(src, num3, this.m_buffer, this.m_startIndex, 20 - num3);
this.m_endIndex += 20 - num3;
return dst;
}
}
return dst;
}