我有两个应用程序:
WPF应用程序能够很好地解密字符串,而ASP.NET应用程序则不能。我已经确保两个应用程序中加密/解密中使用的明文和盐是相同的。
以下是两个应用共享的相关代码:
string Encrypt(string value, SecureString password, string salt)
{
var temp = Marshal.SecureStringToBSTR(password);
var lengthInBytes = Marshal.SizeOf(temp);
// The rest of the encryption code...
}
string Decrypt(string value, SecureString password, string salt)
{
var temp = Marshal.SecureStringToBSTR(password);
var lengthInBytes = Marshal.SizeOf(temp);
// The rest of the decryption code...
}
这里没有错误:两个函数中显示的行确实相同,因为它们应该是恕我直言。
然而,lengthInBytes
内的Decrypt
变量因应用而异。它在ASP.NET(它无法解密)下等于8,在WPF下等于4(两个函数都正常工作)。测试密码明文是“测试”,如果重要的话。
我没有展示其余代码的原因是因为它并不重要。很明显,当存在这种差异时,它不可能正常工作,所以这就是我所关注的。
WPF应用程序直接从SecureString
属性捕获PasswordBox.SecurePassword
。 OTOH,ASP.NET通过在新的AppendChar
实例的循环中调用SecureString
来构建它。我知道这不是那么安全,但是这种情况没有任何可行的非交互式替代方案。虽然这不是重点,但我怀疑它可能是问题的一部分。我只是不知道如何。
我错过了什么?
FWIW,WPF应用程序目前正在其入口可执行文件中使用Obfuscar
工具。我还没有尝试禁用它,看它是否有任何区别。
更新:以下是我在ASP.NET端使用的代码,用于从明文SecureString
创建System.String
:
using (var secure = new SecureString())
{
for (var i = 0; i < plaintext.Length; i++)
{
secure.AppendChar(plaintext[i]);
}
return Decrypt(encrypted, secure, salt);
}
答案 0 :(得分:2)
您错误地使用Marshal.SizeOf
尝试获取字符串长度,但这将返回IntPtr
结构大小。此外,我建议使用unicode编码,以避免因系统编码而对数据进行任何更改:
string Encrypt(string value, SecureString password, string salt)
{
try
{
var temp = Marshal.SecureStringToGlobalAllocUnicode(password);
var lengthInBytes = sizeof(char) * password.Length;
// The rest of the encription code...
}
finally
{
//Cleanup
Marshal.ZeroFreeGlobalAllocUnicode(temp);
}
}
string Decrypt(string value, SecureString password, string salt)
{
try
{
var temp = Marshal.SecureStringToGlobalAllocUnicode(password);
var lengthInBytes = sizeof(char) * password.Length;
// The rest of the decryption code...
}
finally
{
//Cleanup
Marshal.ZeroFreeGlobalAllocUnicode(temp);
}
}
永远记住将内存归零并释放它,否则SecureString的目的就会失败。