首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自WPF的SecureString的PasswordBox与手工构建的PasswordBox不同

来自WPF的SecureString的PasswordBox与手工构建的PasswordBox不同
EN

Stack Overflow用户
提问于 2018-05-06 18:22:23
回答 1查看 291关注 0票数 0

我有两个应用程序:

  1. 通过PasswordBox元素捕获密码并使用它加密C#字符串的WPF应用程序,以及
  2. 一个ASP.NET应用程序,它通过明文配置接收相同的密码,并使用它解密#1中的字符串。

WPF应用程序能够很好地解密字符串,而ASP.NET应用程序则不行。我已经确保了两个应用程序中用于加密/解密的明文和盐类是相同的。

下面是两个应用程序共享的相关代码:

代码语言:javascript
复制
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...
}

这里没有错误:这两个函数中显示的行实际上是相同的,它们,IMHO应该是一样的。

然而,在不同的应用程序之间,lengthInBytes变量在Decrypt中是不同的。在ASP.NET (解密失败)下,它等于8;在WPF下,它等于4(这两个函数都正确工作)。测试密码明文是" test ",如果这很重要的话。

我之所以没有展示其余的代码,是因为它并不重要。很明显,在这种差异存在的情况下,它不可能起作用,所以这就是我所关注的问题。

WPF应用程序直接从SecureString属性捕获PasswordBox.SecurePassword。OTOH,ASP.NET通过在一个新的SecureString实例的循环中调用AppendChar来构建它。我知道这并不安全,但是没有任何可行的非交互的替代方案。虽然这与问题无关,但我怀疑这可能是问题的一部分。我只是还不知道该怎么做。

我错过了什么?

FWIW,WPF应用程序目前正在其入口可执行文件上使用Obfuscar工具。我还没有试着禁用它,看看它是否有任何不同。

UPDATE:下面是我在ASP.NET端使用的代码,用于从纯文本System.String创建SecureString

代码语言:javascript
复制
using (var secure = new SecureString())
{
    for (var i = 0; i < plaintext.Length; i++)
    {
        secure.AppendChar(plaintext[i]);
    }

    return Decrypt(encrypted, secure, salt);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-06 20:17:02

您不正确地使用Marshal.SizeOf试图获取字符串长度,但这将返回IntPtr结构大小。此外,我建议使用unicode编码,以避免由于系统的编码而对数据进行任何更改:

代码语言:javascript
复制
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的目的就会失败。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50203111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档