MemoryStream到SecureString:擦除内存

时间:2015-06-11 18:28:10

标签: c#

我正在从unencrypted检索MemoryStream密钥,将其转换为某种字符串,并使用该字符串和.Net的crypto函数来加密数据。我需要确保在使用它之后从内存中擦除unencrypted密钥。我找到SecureString,我认为它会处理字符串,但我不确定如何在密钥成为SecureString之前擦除密钥的内存。

所以一切正常的方式是:

  

MemoryStream - > char [] - > SecureString的

SecureString传递指向char数组的指针,所以它在完成时擦除了char数组?这是它的构造函数:

SecureString(Char*,int32)

有一个实现它的例子here

然而,一旦SecureString擦除数据(如果擦除数据),我仍然需要知道如何擦除MemoryStream中的数据,以及我必须创建的任何中间对象为了获得char[]

所以这个问题归结为两个部分:

如何直接将MemoryStream读入char[]而不在内存中产生任何其他内容? (如果不可能,那么理想的过渡是什么?即MemoryStream -> string -> char[]?)

和,

完成后如何覆盖MemoryStream(以及MemStream->char[]进程中创建的任何其他签名)使用的内存?

2 个答案:

答案 0 :(得分:2)

首先,SecureString不会擦除输入char*的内存 - 您应对此负责。它只会清理自己的内部存储空间。

要将MemoryStream的内容读取/清除到本地char[],您只需分配数组(假设您的流包含有效字符串):

// Get the contents of the stream.
var byKey = oMS.GetBuffer ();

fixed ( byte *pBytes = byKey )
{
    var oSecStr = new SecureString ( (char*) pBytes, 
        (int) ( oMS.Length / 2 ) );

    // Clear stream (there's no separate char/byte array
    // to clean).
    Array.Clear ( byKey, 0, byKey.Length );
}

这一切当然都假设unsafe代码。但是,没有完全保证从内存中清除密钥的所有潜在实例的方法 - 在将密钥输入流中的调用期间,它可能被复制多次(在各种私有缓冲区中你没有访问)所以你可能甚至不知道徘徊的副本数量。

答案 1 :(得分:1)

您正在尝试的内容比您想象的更成问题。 MemoryStream最有可能被其他东西使用,并且很可能随着时间的推移而增长。

每次增长时,数据都会在内部复制到新数组中,旧数据将被释放=>你的密钥可能泄漏到这里

此外,MemoryStream最有可能被其他API使用。其他API很可能不会安全地删除密钥,因为它们不是为此而设计的。

但是要回答你原来的问题:如果密钥只是ascii字符,你可以将字节复制到char数组中并用随机垃圾覆盖原始字节。您可以使用GetBuffer直接访问其内容。