gpt4 book ai didi

c# - Rfc2898DeriveBytes + PBKDF2 + SecureString 是否可以使用安全字符串而不是字符串?

转载 作者:太空狗 更新时间:2023-10-29 22:14:30 24 4
gpt4 key购买 nike

我有一个函数 GetPassword,它返回一个 SecureString 类型。

当我将此安全字符串传递给 Rfc2898DeriveBytes 以生成 key 时,Visual Studio 显示错误。我有限的知识告诉我这是因为 Rfc2898DeriveBytes 只接受字符串而不是安全字符串。有解决方法吗?

//read the password from terminal
Console.Write("Insert password");
securePwd = myCryptography.GetPassword();

//dont know why the salt is initialized like this
byte[] salt = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xF1, 0xF0, 0xEE, 0x21, 0x22, 0x45 };
try
{ //PBKDF2 standard
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(securePwd, salt, iterationsPwd);

最佳答案

我发现 Rfc2898DeriveBytes 很有趣类不支持 SecureString用于传递用于派生 key 的密码的重载。

WPF 允许使用 PasswordBox 将密码作为 SecureString 对象处理控制。由于我们无法将 SecureString 传递给构造函数,因此失去了此控件提供的附加安全性,这似乎是一种浪费。然而,erickson 提出了使用 byte[] 而不是 string 重载的优点,因为它相对更容易正确管理内容内存中的 byte[]string 多。

使用 erickson 的建议作为灵感,我提出了以下包装器,它应该允许使用受 SecureString 保护的密码值,同时将明文值的暴露降至最低内存。

private byte[] DeriveKey(SecureString password, byte[] salt, int iterations, int keyByteLength)
{
IntPtr ptr = Marshal.SecureStringToBSTR(password);
byte[] passwordByteArray = null;
try
{
int length = Marshal.ReadInt32(ptr, -4);
passwordByteArray = new byte[length];
GCHandle handle = GCHandle.Alloc(passwordByteArray, GCHandleType.Pinned);
try
{
for (int i = 0; i < length; i++)
{
passwordByteArray[i] = Marshal.ReadByte(ptr, i);
}

using (var rfc2898 = new Rfc2898DeriveBytes(passwordByteArray, salt, iterations))
{
return rfc2898.GetBytes(keyByteLength);
}
}
finally
{
Array.Clear(passwordByteArray, 0, passwordByteArray.Length);
handle.Free();
}
}
finally
{
Marshal.ZeroFreeBSTR(ptr);
}
}

这种方法利用了一个事实 BSTR是一个指针,指向具有四字节长度前缀的数据字符串的第一个字符。

要点:

  • 通过将 Rfc2898DeriveBytes 包装在 using 语句中,它确保以确定性方式处理它。这很重要,因为它有一个内部 HMACSHA1 对象,它是一个 KeyedHashAlgorithm 并且需要拥有它拥有的 key (密码)的副本,以便在调用时将其清零处置。参见 Reference Source了解全部详情。
  • 一旦我们完成了 BSTR,我们就将它清零并通过 ZeroFreeBSTR 释放它。 .
  • 最后,我们将密码副本清零。
  • 更新:添加了 byte[] 的固定。正如本 answer 的评论中所讨论的那样,如果 byte[] 没有固定,那么垃圾收集器可以在收集期间重新定位对象,我们将无法将原始副本清零。

这应该将纯文本密码在内存中保留最短的时间,并且不会削弱过多使用 SecureString 的好处。虽然,如果攻击者可以访问 RAM,您可能会遇到更大的问题。另一点是我们只能管理我们自己的密码副本,我们使用的 API 很可能会管理不善(不是清零/清除)他们的副本。据我所知,这不是 Rfc2898DeriveBytes 的情况,尽管它们的 byte[] key (密码)副本未固定,因此数组的痕迹可能如果它在被清零之前在堆中移动,则在附近闲逛。这里的信息是代码看起来很安全,但问题可能隐藏在下面。

如果有人在此实现中发现任何严重漏洞,请告诉我。

关于c# - Rfc2898DeriveBytes + PBKDF2 + SecureString 是否可以使用安全字符串而不是字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9734043/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com