Microsoft在C#中加密/解密的示例代码有一条无法解释的行,它将密钥固定在内存中。我理解钉扎的概念 - 它用于表示GC不应该将该内存的内容移动到其他位置。当然可以。
固定密钥有什么好处?我很确定有一个 - 一个非常聪明的开发人员曾经与我一起工作过,提到这是我们软件安全的重要一步。来自MS article的相关代码。
static void Main()
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;
// Get the key for the file to encrypt.
sSecretKey = GenerateKey();
// For additional security pin the key.
GCHandle gch = GCHandle.Alloc( sSecretKey, GCHandleType.Pinned );
// Encrypt the file.
EncryptFile( @"C:\MyData.txt", @"C:\Encrypted.txt", sSecretKey );
// Decrypt the file.
DecryptFile( @"C:\Encrypted.txt", @"C:\Decrypted.txt", sSecretKey );
// Remove the key from memory.
ZeroMemory( gch.AddrOfPinnedObject(), sSecretKey.Length * 2 );
gch.Free();
}
答案 0 :(得分:11)
这是因为覆盖内存只会覆盖数据所在的位置现在。
如果垃圾收集器已将其移动,则可能存在其先前位置中剩余数据的副本。
为什么不使用SecureString
课程?覆盖System.String
就地违反了其不变量,可能会导致意外行为。然而,SecureString
被设计为被删除,并且不会留下任何副本。
答案 1 :(得分:4)
他通过在完成使用后将内存清零来使其“更安全”。除非固定对象,否则无法直接访问内存字节。如果不将字节清零,字符串将在内存中存在,直到垃圾收集器开始清理它。
有人可以读取您的进程内存并在那里找到密钥。当然,有人仍然可以这样做,只有一个较小的时间窗口可以访问。