在C#中,为什么在内存中固定密钥更安全?

时间:2013-11-15 23:35:56

标签: c# security encryption

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();
}

2 个答案:

答案 0 :(得分:11)

这是因为覆盖内存只会覆盖数据所在的位置现在

如果垃圾收集器已将其移动,则可能存在其先前位置中剩余数据的副本。

为什么不使用SecureString课程?覆盖System.String就地违反了其不变量,可能会导致意外行为。然而,SecureString被设计为被删除,并且不会留下任何副本。

答案 1 :(得分:4)

他通过在完成使用后将内存清零来使其“更安全”。除非固定对象,否则无法直接访问内存字节。如果不将字节清零,字符串将在内存中存在,直到垃圾收集器开始清理它。

有人可以读取您的进程内存并在那里找到密钥。当然,有人仍然可以这样做,只有一个较小的时间窗口可以访问。