我需要从用户那里收集敏感信息字符串。我正在使用WPF PasswordBox
来请求此信息。对于未经启动的人,PasswordBox
控件提供SecurePassword
属性,该属性是SecureString
对象而不是不安全的string
对象。在我的应用程序中,来自PasswordBox
的数据将作为SecureString
传递给加密方法。
我需要做的是将数据封送到基本上代表.Net string
值的字节数组,而无需先将数据转换为.Net string
。更具体地说,给定SecureString
的值为......
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`〜!@#$%^& *()_- + = {[}] |:;“'<,>。?/ ≈母亲
...我怎样才能将它转换为一个字节数组,该数组相当于一个.Net字符串,该字符串已被序列化并写入带StreamWriter
的流?
通过使用Marshal.SecureStringToCoTaskMemUnicode(...)
,我可以使用更传统的西方文本来完成此操作。但是,当我使用其他非典型字符和一串日文文本(请参阅最后几个粗体字符)创建上述文本字符串时,我获取分配给IntPtr
位置的Unicode字节数组的方法不会似乎已经正常工作了。
如何以安全的方式发出SecureString
的数据,使得返回的字节数据的结构与标准.Net字符串的字节数据相同,序列化为二进制输出?
注意
请暂时忽略所有安全问题。我正在为我的应用程序进行各种安全升级。现在,我需要使用SecureString
来获取加密器的敏感数据。解密器(现在)仍然需要将此数据解密为string
值,这就是为什么我需要将SecureString
中的数据序列化为二进制格式,类似于二进制格式string
对象。
我同意这种方法有点不幸,但是,我必须对现有应用程序进行渐进式改进,第一阶段是将SecureString
对象中的数据从用户锁定到加密器
答案 0 :(得分:1)
如果你需要编写安全字符串来流,我建议创建这样的方法:
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();
}
虽然来自第一条评论的方法可能会更加一致(不确定这对你来说是否重要)。