SecureString用法

时间:2014-11-29 21:42:49

标签: c# winforms

一篇文章正在使用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}},将该安全字符串(或安全字符串内容?)传递给该加密方法的安全方法是什么?

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旨在解决的问题,也不是我在此答案中描述的内容解决它。