一篇文章正在使用SecureString文本框控件(http://weblogs.asp.net/pglavich/440191顺便说一句。这是好的类吗?)。然后获取字符串值,它有这样的代码:
using (Crypto cryptor = new Crypto())
{
IntPtr ptr = Marshal.SecureStringToBSTR(password);
this.password = cryptor.EncryptString(Marshal.PtrToStringAuto(ptr));
Marshal.ZeroFreeBSTR(ptr);
}
当被要求Marshal.PtrToStringAuto(ptr)
也创建一个字符串时(应该是
不安全),作者回答它在using
内,而string
应该在using
内
在那里说一秒钟 - 然后被摧毁。我的问题是,这是真的吗?我认为是SecureString
个关键字
仅适用于Crypto对象,不是吗?为什么它适用于字符串?
最后,假设我使用Encrypt(string password, byte[] data)
文本框控件。并假设我有
一些安全帮助方法,如Encrypt(byte [] key, byte [] data)
,甚至{{1}},将该安全字符串(或安全字符串内容?)传递给该加密方法的安全方法是什么?
答案 0 :(得分:0)
我的问题是,这是真的吗?我以为
using
关键字只适用于Crypto对象,不是吗?为什么它适用于字符串?
这是正确的:它不适用于string
类型。
using
只是意味着在cryptor.Dispose()
块被留下后会调用using
,但cryptor
完全无法修改任何string
对象也不应该:那不是它的工作。
最后,假设我使用
SecureString
文本框控件。并假设我有一些安全帮助方法,如Encrypt(string password, byte[] data)
,甚至Encrypt(byte [] key, byte [] data)
,将该安全字符串(或安全字符串内容?)传递给该加密方法的安全方法是什么?
使用Encrypt(string password, byte[] data)
方法,这是不可能的。 string
对象的内容无法覆盖,因为字符串是不可变的,因此在对字符串进行垃圾回收之前,无法从内存中清除密码。一旦字符串被垃圾收集,内存仍然无法清除,您不再知道需要清除的内存。
使用Encrypt(byte[] key, byte[] data)
,有可能。
首先必须固定阵列(在之前填充其内容),以便垃圾收集器无法在内存中移动它。您可以使用GCHandle.Alloc
。确保通过GCHandleType.Pinned
。这可确保密钥仅存在于内存中的单个位置。
这是您可以安全地传递给Encrypt
方法的内容。
然后,在完成该键之后,可以将该数组中的所有字节重新设置为零。由于阵列仍然固定,因此您可以确定该密钥在进程内存中的其他位置不存在。
最后,不要忘记致电gcHandle.Free()
以防止您的阵列永远徘徊。
注意:还有其他安全的方式来处理SecureString
,但它们涉及指针,而不是您给出的两个特定Encrypt
签名的选项。
注2:这个答案的基本假设,以及SecureString
一般来说,应该最小化密码保存在内存中未加密的时间。代码未处理任何密码时的崩溃转储不应泄露任何密码。 SecureString
还没有解决其他有效问题:您自己的计算机上的恶意程序显然会在您的进程中注入代码,以完全像您自己的进程那样解密字符串。这不是SecureString
旨在解决的问题,也不是我在此答案中描述的内容解决它。