在处理SymmetricAlgorithm时,“try-finally”阻止与“使用”块

时间:2011-06-29 21:32:13

标签: c# .net encryption

根据msdn docs for System.Security.Cryptography.SymmetricAlgorithm

  

请注意,在使用派生类时,从安全角度来看,仅在使用完对象后强制执行垃圾回收是不够的。必须在对象上显式调用Clear方法,才能在对象释放之前将其中的任何敏感数据清零。请注意,垃圾收集不会将收集的对象的内容清零,而只是将内存标记为可用于重新分配。因此,垃圾收集对象中包含的数据可能仍然存在于未分配的存储器中的存储器堆中。对于加密对象,此数据可能包含敏感信息,如密钥数据或纯文本块。

     

.NET Framework中包含敏感数据的所有加密类都实现了Clear方法。调用时,Clear方法用零覆盖对象中的所有敏感数据,然后释放该对象,以便可以安全地进行垃圾回收。当对象已归零并释放时,您应该调用Dispose方法并将disposing参数设置为True,以处置与该对象关联的所有托管和非托管资源。

我从中获得的是我必须使用try-finally块来处理我的算法,如下所示:

SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create()
try 
{
     //stuff
}
finally
{
    symmetricAlgorithm.Clear();
    symmetricAlgorithm.Dispose(true)
}

我无法使用更简洁的using

using (var symmetricAlgorithm = SymmetricAlgorithm.Create())
{
    //do stuff
}

因为它不会清除内存。它只会标记为收藏。那是对的吗?谢谢您的帮助。

2 个答案:

答案 0 :(得分:17)

  

[调用Dispose]只会将其标记为收藏。这是对的吗?

不,这不对。你对“Dispose”的作用有误解。这是一个非常普遍的误解。

让我在这一点上非常清楚:“Dispose”本身与垃圾收集完全无关。“Dispose”没有什么特别的,你在其他任何地方都做不到任何其他名称的方法。很多人都相信以下神话:

  • 在实现名为IDisposable的接口的对象上调用名为Dispose的方法“标记”要收集的对象。
  • 垃圾收集器在收集对象时调用IDisposable.Dispose。

这些神话都不是真的。

事实是:

  • 完成对象后调用“Dispose”是约定,旨在确保清除非托管资源 之前,垃圾收集器开始清理与对象关联的托管内存资源

  • 垃圾收集器根据是否可以通过已知的活动对象访问对象的任何引用来决定何时收集对象。调用“Dispose”或任何其他方法不会使对象无法访问。

  • 垃圾收集器(有时)会在收集对象之前不久调用一个“终结器”(也称为“析构函数”)。作为惯例,对象的作者通常选择使对象的最终化与其处置相同。但同样,这只是一个惯例。

  • 作为惯例,刚刚处置的对象应告诉垃圾收集器GC最终无法访问时可以安全地跳过此对象的完成。

“Dispose”只是一种方法。如果该方法碰巧告诉GC一堆东西,比如“顺便说一下,有人已经负责完成这个对象”,那么该方法可以自由地进行。 “Dispose”中没有固有的魔力。您可以编写自己的方法“MyDispose”和您自己的界面“IMyDisposable”,它们做同样的事情; GC既不知道也不关心您选择哪些约定来组织代码,以便尽早释放非托管资源。

答案 1 :(得分:11)

以下是Clear方法的实现方法(来自Reflector):

public void Clear()
{
    ((IDisposable) this).Dispose();
}

所以你可以使用using阻止。