重用 ICryptoTransform 对象

2023-11-26

我有一个用于加密文本数据的类。我正在尝试尽可能重用 ICryptoTransform 对象。但是,当我第二次尝试使用同一对象时,我得到了部分错误解密的数据。我认为第一个块是错误的,但其余的似乎没问题(用较长的文本进行了测试)。

我将课程精简为以下内容:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Sample.Crypto
{
    public class EncryptedStreamResolver : IDisposable
    {
        private AesCryptoServiceProvider _cryptoProvider;
        private ICryptoTransform _encryptorTransform;
        private ICryptoTransform _decryptorTransform;

        private ICryptoTransform EncryptorTransform
        {
            get
            {
                if (null == _encryptorTransform || !_encryptorTransform.CanReuseTransform)
                {
                    _encryptorTransform?.Dispose();
                    _encryptorTransform = _cryptoProvider.CreateEncryptor();
                }
                return _encryptorTransform;
            }
        }

        private ICryptoTransform DecryptorTransform
        {
            get
            {
                if (null == _decryptorTransform || !_decryptorTransform.CanReuseTransform)
                {
                    _decryptorTransform?.Dispose();
                    _decryptorTransform = _cryptoProvider.CreateDecryptor();
                }
                return _decryptorTransform;
            }
        }

        public EncryptedStreamResolver()
        {
            GenerateCryptoProvider();
        }

        public Stream OpenRead(string rawPath)
        {
            return new CryptoStream(File.OpenRead(rawPath + ".crypto"), DecryptorTransform, CryptoStreamMode.Read);
        }

        public Stream OpenWrite(string rawPath)
        {
            return new CryptoStream(File.OpenWrite(rawPath + ".crypto"), EncryptorTransform, CryptoStreamMode.Write);
        }

        private void GenerateCryptoProvider(string password = "totallysafepassword")
        {
            _cryptoProvider = new AesCryptoServiceProvider();
            _cryptoProvider.BlockSize = _cryptoProvider.LegalBlockSizes.Select(ks => ks.MaxSize).Max();
            _cryptoProvider.KeySize = _cryptoProvider.LegalKeySizes.Select(ks => ks.MaxSize).Max();
            _cryptoProvider.IV = new byte[_cryptoProvider.BlockSize / 8];
            _cryptoProvider.Key = new byte[_cryptoProvider.KeySize / 8];

            var pwBytes = Encoding.UTF8.GetBytes(password);
            for (var i = 0; i < _cryptoProvider.IV.Length; i++)
                _cryptoProvider.IV[i] = pwBytes[i % pwBytes.Length];
            for (var i = 0; i < _cryptoProvider.Key.Length; i++)
                _cryptoProvider.Key[i] = pwBytes[i % pwBytes.Length];
        }

        public void Dispose()
        {
            _encryptorTransform?.Dispose();
            _decryptorTransform?.Dispose();
            _cryptoProvider?.Dispose();
        }
    }
}

我编写了一个示例使用测试来演示该问题:

public void Can_reuse_encryptor()
{
    const string message = "Secret corporate information here.";
    const string testFilePath1 = "Foo1.xml";
    const string testFilePath2 = "Foo2.xml";
    var sr = new EncryptedStreamResolver();

    // Write secret data to file
    using (var writer = new StreamWriter(sr.OpenWrite(testFilePath1)))
        writer.Write(message);

    // Read it back and compare with original message
    using (var reader = new StreamReader(sr.OpenRead(testFilePath1)))
        if (!message.Equals(reader.ReadToEnd()))
            throw new Exception("This should never happend :(");

    // Write the same data again to a different file
    using (var writer = new StreamWriter(sr.OpenWrite(testFilePath2)))
        writer.Write(message);

    // Read that back and compare
    using (var reader = new StreamReader(sr.OpenRead(testFilePath2)))
        if (!message.Equals(reader.ReadToEnd()))
            throw new Exception("This should never happend :(");
}

我缺少什么?文档表明这些对象是可重用的,但我不明白如何重用。有人能帮助我吗?

EDIT:

正如 @bartonjs 指出的,如果我将包含上述代码的项目重新定位到 .NET 4.6(或更高版本),我可以使用System.AppContext.TryGetSwitch像这样:

var reuseTransform = false;
if (null == _decryptorTransform ||
    !(AppContext.TryGetSwitch("Switch.System.Security.Cryptography.AesCryptoServiceProvider.DontCorrectlyResetDecryptor", out reuseTransform) && reuseTransform && _decryptorTransform.CanReuseTransform))
{
    _decryptorTransform?.Dispose();
    _decryptorTransform = _cryptoProvider.Createdecryptor();
}

然后我可以在主应用程序的 app.config 中设置此开关,如 @bartonjs 的答案。


您缺少的是 .NET Framework 中的错误(和错误修复):)。

有一个微软连接问题关于同样的问题;具体来说,AesCryptoServiceProvider.CreateDecryptor() 返回一个对象,其中包含CanReuseTransform=true,但似乎行为不正确。

该错误已在 .NET 4.6.2 版本中修复,但受到保护重新定位改变。这意味着要查看修复程序,您需要

  1. 安装 .NET Framework 4.6.2 或更高版本。
  2. 将主可执行文件的最低框架版本更改为 4.6.2 或更高版本。

如果您安装了较新的框架,但希望保持可执行文件针对较低版本的框架,则需要设置开关Switch.System.Security.Cryptography.AesCryptoServiceProvider.DontCorrectlyResetDecryptor to false.

来自AppContext 类文档(在“备注”下):

一旦定义并记录了开关,调用者就可以通过使用注册表、将 AppContextSwitchOverrides 元素添加到其应用程序配置文件或通过调用AppContext.SetSwitch(String, Boolean)以编程方式进行方法。

对于配置文件(your.exe.config):

<configuration>
  <runtime>
    <AppContextSwitchOverrides
      value="Switch.System.Security.Cryptography.AesCryptoServiceProvider.DontCorrectlyResetDecryptor=false" />
  </runtime>
</configuration>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重用 ICryptoTransform 对象 的相关文章

  • 如何从字符串中提取子字符串直到遇到第二个空格?

    我有一个像这样的字符串 o1 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 如何仅提取 o1 1232 5467 要提取的字符数并不总是相同 因此 我只想提取直到遇到
  • 静态构造函数和 BeforeFieldInit?

    如果类型没有静态构造函数 则将执行字段初始值设定项 就在使用该类型之前 或者在某个时间点突发奇想 运行时 为什么这段代码 void Main start Dump Test EchoAndReturn Hello end Dump clas
  • 在 C 语言中,为什么数组的地址等于它的值?

    在下面的代码中 指针值和指针地址与预期不同 但数组值和地址则不然 怎么会这样 Output my array 0022FF00 my array 0022FF00 pointer to array 0022FF00 pointer to a
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • Boost ASIO 串行写入十六进制值

    我正在使用 ubuntu 通过串行端口与设备进行通信 所有消息都必须是十六进制值 我已经在 Windows 环境中使用白蚁测试了通信设置 并得到了我期望的响应 但在使用 Boost asio 时我无法得到任何响应 以下是我设置串口的方法 b
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • if constexpr 中的 not-constexpr 变量 – clang 与 GCC

    struct A constexpr operator bool const return true int main auto f auto v if constexpr v A a f a clang 6 接受该代码 GCC 8 拒绝它
  • OpenGL:如何检查用户是否支持glGenBuffers()?

    我检查了文档 它说 OpenGL 版本必须至少为 1 5 才能制作glGenBuffers 工作 用户使用的是1 5版本但是函数调用会导致崩溃 这是文档中的错误 还是用户的驱动程序问题 我正在用这个glGenBuffers 对于VBO 我如
  • 来自嵌入图像的 BitmapSource

    我的目标是在 WPF 窗口上重写 OnRender 方法中绘制图像 someImage png 它是嵌入资源 protected override void OnRender System Windows Media DrawingCont
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 我们可以通过指针来改变const定义的对象的值吗?

    include
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • ASP.NET Core 中间件与过滤器

    在阅读了 ASP NET Core 中间件之后 我对何时应该使用过滤器以及何时应该使用中间件感到困惑 因为它们似乎实现了相同的目标 什么时候应该使用中间件而不是过滤器 9频道有一个关于此的视频 ASP NET 怪物 91 中间件与过滤器 h
  • 当Model和ViewModel一模一样的时候怎么办?

    我想知道什么是最佳实践 我被告知要始终创建 ViewModel 并且永远不要使用核心模型类将数据传递到视图 这就说得通了 让我把事情分开 但什么是Model 和ViewModel一模一样 我应该重新创建另一个类还是只是使用它 我觉得我应该重
  • Unity3D - 将 UI 对象移动到屏幕中心,同时保持其父子关系

    我有一个 UI 图像 它的父级是 RectTransform 容器 该容器的父级是 UI 面板 而 UI 面板的父级是 Canvas 我希望能够将此 UI 图像移动到屏幕中心 即画布 同时保留父级层次结构 我的目标是将 UI 图像从中心动画
  • C:设置变量范围内所有位的最有效方法

    让我们来int举个例子 int SetBitWithinRange const unsigned from const unsigned to To be implemented SetBitWithinRange应该返回一个int其中所有
  • 如何在 ASP.NET Core 中注入泛型的依赖关系

    我有以下存储库类 public class TestRepository Repository

随机推荐

  • 使用侧列表托盘嵌入 YouTube 播放列表

    我一直在使用 javascript 使用 youtube 嵌入播放列表功能 到目前为止 当我嵌入播放列表时 它看起来像这样 http postimage org image vk6fv56yx 蓝色圆圈显示播放列表中的项目数 单击时会显示缩
  • 如何仅比较 EF 中 DateTime 的日期组件?

    我有两个日期值 一个已存储在数据库中 另一个由用户使用 DatePicker 选择 用例是从数据库中搜索特定日期 先前在数据库中输入的值始终具有 12 00 00 的时间部分 而从选择器输入的日期具有不同的时间部分 我只对日期部分感兴趣 想
  • 如何使用 root 在 Android 4.2 及更高版本上切换飞行模式?

    众所周知 在 Android 4 2 上 只有系统应用程序可以切换飞行模式 但我认为它必须适用于 root 设备 我想在我的应用程序中将其实现为具有 Build VERSION SDK INT gt 17 的 root 设备 如何在 And
  • 根据一组关键字进行搜索

    我需要根据一组关键字进行搜索 返回与这些关键字相关的所有广告 然后结果是一个类别列表 其中包含每个类别的广告计数 搜索是在 KeywordSearch 表中进行的 public class KeywordSearch public int
  • 我可以在不使用 Array 构造函数或数组文字的情况下创建 Array.isArray() 返回 true 的对象吗?

    我可以通过将其原型设置为轻松使普通对象看起来像数组Array prototype const obj Reflect setPrototypeOf obj Array prototype 我知道魔法也存在一些问题length属性和稀疏数组
  • 使用 UIScreenEdgePanGestureRecognizer 而不移动 MKMapView

    我有一个包含 MKMapView 的 UIViewController 事实上 它包含一个包含 MKMapView 的全屏容器 但它不应该有任何影响 我实现了一个 UIScreenEdgePanGestureRecognizer 以显示抽屉
  • Quantmod add_TA 和 Chart_Series 出现问题 - 调用下一个 add_TA 后线条和文本消失

    我正在使用新的chart Series and add TA非常多 它对我来说非常有效 我发现它非常有用 我正在尝试在图表上添加一些内容 水平线和一些文本 这里开始出现问题 正确绘制水平线和文本后 如果我调用后续命令 它们就会消失add T
  • Cassandra控制SSTable大小

    有没有办法控制 SSTable 的最大大小 例如 100 MB 这样当 CF 实际上有超过 100MB 的数据时 Cassandra 就会创建下一个 SSTable 不幸的是 答案并不那么简单 SSTable 的大小将受到压缩策略的影响 并
  • C语言中的限定符是什么?

    我正在这个网址阅读一些文字 https cs senecac on ca btp100 pages content varia p html 在 限定符 部分中 他们说 我们可以限定 int 类型以确保它包含最少位数 Short 至少包含
  • 在 ANSI C 中正确声明 main() 函数 [重复]

    这个问题在这里已经有答案了 C标准说 程序启动时调用的函数 被命名为主 实施情况 没有为此声明原型 功能 它应定义为 返回类型为 int 并且没有 参数 int main void 或带有两个参数 参考 这里作为 argc 和 argv 尽
  • 如何在 Isabelle/jEdit 中启用“跟踪”

    I m a vim风扇 但仅emacs有这个 Isabelle HOL 环境 jEdit很棒 但我不能使用 using simp trace true like in emacs 如何启用 跟踪 jEdit 你确实可以使用simp trac
  • 将函数应用于多维数组:R 与 MATLAB

    这个问题可以被认为与this one 这帮助我提高了 R 在计算大数组平均值时的性能 不幸的是 在这种情况下 我尝试应用更复杂的东西 例如分位数计算 我有一个包含超过 4000 万个元素的 4 维数组 我想计算特定维度上的第 66 个百分位
  • 更改 GridView 的行为以使其水平滚动而不是垂直滚动

    我想做一个UI像一个元素GridView 我希望它具有完整的功能 但希望它可以水平滚动而不是垂直滚动 通过水平滚动 我的意思是它应该以这种方式构建 而不是放在一个HorizontalScrollView 我的会是Custom GridVie
  • 在 NodeJS 中下载大文件的最佳方法是什么?

    下面的服务器代码对于 5GB 文件运行良好wget http localhost 11146 base bigFile zip但不使用客户端代码 服务器端代码 var http require http var fs require fs
  • Ninject 与 MembershipProvider |角色提供者

    我使用 ninject 作为我的 IoC 并编写了一个角色提供程序 如下所示 public class BasicRoleProvider RoleProvider private IAuthenticationService authen
  • 为什么 git rebase 会触发合并冲突?

    我已经克隆了一个远程存储库 创建了一个新分支b并开始工作并做出承诺 我也推了b分支 但我是唯一一个在这方面工作的人 一段时间后 我想在远程主分支上重新设置本地分支的基础 只是为了与系统可能发生的更改同步 请注意 我确信我是唯一处理这些特定文
  • Python 3 和 tkinter 通过单击按钮打开新窗口

    当用户单击 Tkinter 和 Python 3 中的按钮时 如何打开新窗口 您可以通过创建 Tkinter 类的新实例来打开新窗口Toplevel 例如 import Tkinter as tk class View tk Frame c
  • 将 geoJson 数据转换为 SQL Server 空间数据类型 (GIS)

    我已经从 openstreetmaps 下载了 geoJson 格式的行政边界 城市 地区 国家等 我正在尝试使用空间数据将与多边形相关的 json 数据存储在我的 MS sql 服务器中 由于我从未解析过如此复杂的 json 文件 因此我
  • 在 JPA DTO 投影查询中加载子集合 DTO

    我在 Wildfly 10 1 0 Final 上使用 Java EE 7 与 Java 8 和 Hibernate 5 0 X 并且需要使用投影将 JPQL 查询结果加载到 DTO 中 但我找不到任何有关如何执行此操作的文档同时加载子集合
  • 重用 ICryptoTransform 对象

    我有一个用于加密文本数据的类 我正在尝试尽可能重用 ICryptoTransform 对象 但是 当我第二次尝试使用同一对象时 我得到了部分错误解密的数据 我认为第一个块是错误的 但其余的似乎没问题 用较长的文本进行了测试 我将课程精简为以