代码之家  ›  专栏  ›  技术社区  ›  mckamey

.NET加密类的线程安全性?

  •  13
  • mckamey  · 技术社区  · 15 年前

    我有一个高水平的目标,就是创造一个 静止的 用于封装.NET应用程序加密的实用程序类。在内部,我想最小化不必要的对象创建。

    我的问题是: 在.NET框架内实现对称加密的类的线程安全性是什么? 明确地 System.Security.Cryptography.RijndaelManaged 以及 ICryptoTransform 它生成的类型。

    例如,在我的类构造函数中,我可以简单地沿着以下几行做一些事情吗?

    static MyUtility()
    {
        using (RijndaelManaged rm = new RijndaelManaged())
        {
            MyUtility.EncryptorTransform = rm.CreateEncryptor(MyUtility.MyKey, MyUtility.MyIV);
            MyUtility.DecryptorTransform = rm.CreateDecryptor(MyUtility.MyKey, MyUtility.MyIV);
        }
    }
    

    在这个类中存在密钥和IV是否安全? ,此示例块还提出了一些其他问题:

    1. 我是否可以反复使用加密或解密转换和解密转换?这个 *.CanReuseTransform *.CanTransformMultipleBlocks 房产意味着“是的”,但有什么需要注意的吗?

    2. 自从 RijndaelManaged 器具 IDisposable 我想把它放在 using 尤其是因为它可能与外部操作系统级libs关联。因为我保留了 微囊转运 周围物体?

    3. 在高度多线程的环境中,最重要的潜在问题是,我是否会遇到共享 微囊转运 线程之间的对象?

    4. 如果3的答案是它不是线程安全的,那么在使用 微囊转运 物体?(我想取决于负载。)

    5. 简单地实例化新的 RijnDaeldMultualMultualMul 每一次?或存储一个 RijnDaeldMultualMultualMul 生成 new RijndaelManaged().CreateEncryptor(...) 每一次?

    我希望外面的人知道这些是如何在幕后工作的,或者对来自类似实现的问题有经验。我发现,很多此类性能和线程相关的问题通常在有相当大的负载之前都不会表现出来。

    谢谢!

    2 回复  |  直到 11 年前
        1
  •  15
  •   Reed Copsey    15 年前

    1)是的。

    2)如果你丢弃了它,你就不能使用它。在此之前,您可以共享/使用它(但请参见下文)

    3-4)来自 MSDN :

    “此类型的任何公共静态(在VisualBasic中共享)成员都是线程安全的。任何实例成员都不能保证是线程安全的。”

    如果您希望保持这个状态,并在线程之间共享它,那么需要实现锁定并将其视为锁定的资源。否则,我建议您根据需要制作单独的版本,并在完成后进行处理。

    5)我建议您根据需要创建这些,然后在稍后发现性能问题时尝试对其进行优化。在分析后发现这是一个问题之前,不要担心创建新版本的性能影响。

        2
  •  3
  •   Andreas    11 年前

    只需使用基于并发堆栈的缓存就可以解决并发问题:

    static ConcurrentStack<ICryptoTransform> decryptors = new ConcurrentStack<ICryptoTransform>();
    
    void Encrypt()
    {
       // Pop decryptor from cache...
       ICryptoTransform decryptor;
       if (!decryptors.TryPop(out decryptor))
       {
           // ... or create a new one since cache is depleted
           AesManaged aes = new AesManaged();
           aes.Key = key;
           aes.IV = iv;
           decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        }
    
        try
        {
           //// use decryptor
        }
        finally
        {
           decryptors.Push(decryptor);
        }
     }