如何正确地从 SecureString 发出二进制数据,以便以后可以将其转换为字符串?

How do I properly emit binary data from a SecureString, so that it can later be converted to a string?

我有一些敏感信息需要从我的用户那里收集。我正在使用 WPF PasswordBox 来请求此信息。对于初学者,PasswordBox 控件提供了一个 SecurePassword 属性,它是一个 SecureString 对象,而不是不安全的 string 对象。在我的应用程序中,来自 PasswordBox 的数据作为 SecureString 传递给加密方法。

我需要做的是将数据编组为一个字节数组,该数组本质上表示一个 .Net string 值,而无需先将数据转换为 .Net string。更具体地说,给定一个 SecureString 的值,例如...

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`~!@#$%^&*()_-+={[}]|:;"'<,>.?/ ≈篭母

...我如何将它转换为一个字节数组,该字节数组等同于已序列化并写入带有 StreamWriter 的流的 .Net 字符串?

通过使用 Marshal.SecureStringToCoTaskMemUnicode(...),我可以使用更传统的西方文本来做到这一点。但是,当我使用额外的非典型字符和一串日语文本(请参阅最后几个粗体字符)创建上述文本字符串时,我获取分配给 IntPtr 位置的 Unicode 字节数组的方法没有似乎可以正常工作了。

如何以安全的方式发出 SecureString 的数据,使返回的字节数据的结构与标准 .Net 字符串的字节数据相同,序列化为二进制输出?

注意

请暂时忽略所有安全问题。我正在努力对我的应用程序进行各种安全升级。现在,我需要使用 SecureString 将敏感数据发送到加密器。解密器(现在)仍然需要将此数据解密为 string 值,这就是为什么我需要一些如何将 SecureString 中的数据序列化为类似于二进制格式的二进制格式的原因string 对象。

我同意这种方法有点不幸,但是,我必须对现有应用程序进行增量改进,第一阶段是锁定 SecureString 对象中的数据,从用户到加密器。

如果您需要将安全字符串写入流,我建议创建这样的方法:

public static class Extensions {
    public static void WriteSecure(this StreamWriter writer, SecureString sec) {
        int length = sec.Length;
        if (length == 0)
            return;
        IntPtr ptr = Marshal.SecureStringToBSTR(sec);
        try {
            // each char in that string is 2 bytes, not one (it's UTF-16 string)
            for (int i = 0; i < length * 2; i += 2) {
                // so use ReadInt16 and convert resulting "short" to char
                var ch = Convert.ToChar(Marshal.ReadInt16(ptr + i));
                // write
                writer.Write(ch);
            }
        }
        finally {
            // don't forget to zero memory
            Marshal.ZeroFreeBSTR(ptr);
        }
    }
}

如果你真的需要字节数组——你也可以重用这个方法:

byte[] result;
using (var ms = new MemoryStream()) {
    using (var writer = new StreamWriter(ms)) {
        writer.WriteSecure(secureString);
    }
    result = ms.ToArray();
}

尽管第一个评论中的方法可能更麻烦(不确定这对您是否重要)。