安全字符串用法
本文关键字:用法 字符串 安全 | 更新日期: 2023-09-27 18:32:32
一篇文章使用了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
文本框控件。并假设我有一些安全帮助程序方法,如Encrypt(string password, byte[] data)
,甚至Encrypt(byte [] key, byte [] data)
,将安全字符串(或安全字符串内容?(传递给该加密方法的安全方法是什么?
我的问题是,这是真的吗?我认为
using
关键字仅适用于 Crypto 对象,不是吗?为什么它适用于字符串?
没错:它不适用于类型 string
.
using
只是意味着一旦using
块被留下,cryptor.Dispose()
就会被调用,但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
旨在解决的问题,我也不声称我在这个答案中描述的问题解决了它。