【问题标题】:How to use a CNG (or AES-NI enabled instruction set) in .NET?如何在 .NET 中使用 CNG(或启用 AES-NI 的指令集)?
【发布时间】:2011-11-15 17:07:31
【问题描述】:

我目前使用 AES 在 c# 中执行大量的文本加密/解密。

如果使用纯软件系统,则需要在相当长的时间内对大量需要解密的数据集进行相当长的处理器打击。我知道英特尔已经推出了他们的 AES-NI 指令集,而 AMD 也推出了类似的指令集。

我正在使用 .NET 4.0,我知道 windows CNG 框架使用这些指令集,但似乎 .NET 世界中的 AesManaged 并没有这样做。

有一个很棒的项目“CLR Security”,它是一个从 .NET 3.5 到 windows CNG 的网关,但是它已经一年没有维护了,我宁愿不(如果可能的话)跳到垂死的路上项目。

.NET 4 中有一个 CNGProvider 类,但似乎没有足够的文档来拼凑从中用于 AES 的有效解密。

有没有人对此主题有经验,他们可以为我指明正确的方向,即如何使用预制类在纯 .NET 环境中实现 AES-NI,而无需直接从 c# 执行 p/invoke? (如果有一个包装类来做就好了,只要它被维护)。

【问题讨论】:

  • AesCryptoServiceProvider 怎么样?它说使用 CAPI,因此希望 CNG 可用。
  • 我要试一试,问题是没有一些不错的文档,那么唯一的判断方法是基准测试,所以当我能得到一些结果时会进行测试并报告。
  • @Rup:有没有关于 CAPI 利用 CNG 的文档(如果有的话)?我的理解是 CAPI 和 CNG 在底层是完全独立的 API。我们正在对此进行调查,因此您的意见会有所帮助。
  • @Sid 不,我不记得我在哪里找到的 - 抱歉。

标签: c# .net-4.0 cryptography aes cng


【解决方案1】:

AesCryptoServiceProvider 呢?它说使用CAPI,所以 希望CNG(如果有的话)。 – 鲁普

这条评论有很大帮助,在进行了一些挖掘之后,看起来AesCryptoServiceProvider 将使用 AES-NI(如果可用)。但是,我找不到任何来自 Microsoft 的“官方”文档。在运行简单的时序基准测试时,速度差异约为 15 倍,因此 API 本身已经过大规模优化(对于 15 倍的提升来说是相当不错的优化),或者它使用 AES-NI 指令集。

很遗憾,我没有可以测试的非 AES-NI 机器,但如果我得到一个,我会用结果更新这个线程。

所以我非常有信心这是用于 AES-NI 的 API,但如果没有进一步测试,我无法保证。

【讨论】:

  • 想要回来查看 - 是否确认 AesCryptoServiceProvider 确实在 Windows Server 2008 R2/2012 上使用了 CNG 而不是 CAPI 本身?谢谢!
  • 嗨 Sid,当我在非 AES-NI 机器上使用它时,性能显着下降,但是我仍然没有看到任何来自 Microsoft 的文档来 100% 证实我的信念。然而,在这一点上,我假设它使用了 AES-NI 指令集(我相信这是一个非常安全的假设)。
  • 我相信使用下一代密码术 (CNG) 的 Windows 7 及更高版本确实支持 AES-NI。
  • 至少在我的支持 AES-NI(64 位,i7-3520M,常春藤桥)的 Win7 机器上,AesCryptoServiceProvider 以每字节大约 23 个周期运行。所以它不太可能使用AES-NI。一个适当的基于 AES-NI 的实现应该比这快至少 10 倍。
【解决方案2】:

如何在 .NET 中使用 CNG(或启用 AES-NI 的指令集)?

我将专注于 AES-NI 指令集问题。我发现它很有趣,因为我自己也想知道它(用于 C 和 C++)。

Microsoft 将 AES-NI 支持添加到 Visual Studio 2008 SP1 (_MSC_FULL_VER >= 150030729)。最早可以在 Microsoft 产品中观察到 AES-NI 是在 2008 年左右,因为早期的编译器不支持它。这意味着 Server 2008 拥有它,可能还有通过 Service Pack 的 Windows Vista 及更高版本。

根据Does MS Crypto API supports AES and AES-NI processor instructions?rsaenh.dllbcryptprimitives.dll 都有。 IvanP 的声明在 Windows 7 和 Windows 10 上进行了测试。

但是,在 Windows 8.1 上进行的测试显示...

# Using a Developer Command prompt so dumpbin is on-path:
> dumpbin /disasm c:\Windows\System32\rsaenh.dll > rsaenh.dll.txt
> dumpbin /disasm c:\Windows\System32\bcryptprimitives.dll > bcryptprimitives.dll.txt

然后:

# Using a GitBash terminal for grep
$ grep -i aes rsaenh.dll.txt
$

还有:

$ grep -i aes bcryptprimitives.dll.txt
  000000018000234A: 66 0F 3A DF C0 00  aeskeygenassist xmm0,xmm0,0
  0000000180002363: 66 0F 38 DB C0     aesimc      xmm0,xmm0
  000000018000237E: 66 0F 38 DC 41 10  aesenc      xmm0,xmmword ptr [rcx+10h]
  0000000180002384: 66 0F 38 DC 41 20  aesenc      xmm0,xmmword ptr [rcx+20h]
  000000018000238A: 66 0F 38 DC 41 30  aesenc      xmm0,xmmword ptr [rcx+30h]
  0000000180002390: 66 0F 38 DC 41 40  aesenc      xmm0,xmmword ptr [rcx+40h]
  0000000180002396: 66 0F 38 DC 41 50  aesenc      xmm0,xmmword ptr [rcx+50h]
  000000018000239C: 66 0F 38 DC 41 60  aesenc      xmm0,xmmword ptr [rcx+60h]
  00000001800023A2: 66 0F 38 DC 41 70  aesenc      xmm0,xmmword ptr [rcx+70h]
  00000001800023AF: 66 0F 38 DC 01     aesenc      xmm0,xmmword ptr [rcx]
  00000001800023B4: 66 0F 38 DC 41 10  aesenc      xmm0,xmmword ptr [rcx+10h]
  00000001800023C3: 66 41 0F 38 DD 02  aesenclast  xmm0,xmmword ptr [r10]
  000000018001936E: 66 0F 38 DC 41 10  aesenc      xmm0,xmmword ptr [rcx+10h]
  0000000180019374: 66 0F 38 DC 41 20  aesenc      xmm0,xmmword ptr [rcx+20h]
  000000018001937A: 66 0F 38 DC 41 30  aesenc      xmm0,xmmword ptr [rcx+30h]
  0000000180019380: 66 0F 38 DC 41 40  aesenc      xmm0,xmmword ptr [rcx+40h]
  0000000180019386: 66 0F 38 DC 41 50  aesenc      xmm0,xmmword ptr [rcx+50h]
  000000018001938C: 66 0F 38 DC 41 60  aesenc      xmm0,xmmword ptr [rcx+60h]
  0000000180019392: 66 0F 38 DC 41 70  aesenc      xmm0,xmmword ptr [rcx+70h]
  000000018001939F: 66 0F 38 DC 01     aesenc      xmm0,xmmword ptr [rcx]
  00000001800193A4: 66 0F 38 DC 41 10  aesenc      xmm0,xmmword ptr [rcx+10h]
  00000001800193B3: 66 41 0F 38 DD 02  aesenclast  xmm0,xmmword ptr [r10]
  000000018001952E: 66 0F 38 DE C4     aesdec      xmm0,xmm4
  0000000180019533: 66 0F 38 DE CC     aesdec      xmm1,xmm4
  0000000180019538: 66 0F 38 DE D4     aesdec      xmm2,xmm4
  000000018001953D: 66 0F 38 DE DC     aesdec      xmm3,xmm4
  000000018001954B: 66 0F 38 DF C4     aesdeclast  xmm0,xmm4
  0000000180019550: 66 0F 38 DF CC     aesdeclast  xmm1,xmm4
  0000000180019555: 66 0F 38 DF D4     aesdeclast  xmm2,xmm4
  000000018001955A: 66 0F 38 DF DC     aesdeclast  xmm3,xmm4
  000000018002E8B5: 66 0F 38 DE 41 10  aesdec      xmm0,xmmword ptr [rcx+10h]
  000000018002E8BB: 66 0F 38 DE 41 20  aesdec      xmm0,xmmword ptr [rcx+20h]
  000000018002E8C1: 66 0F 38 DE 41 30  aesdec      xmm0,xmmword ptr [rcx+30h]
  000000018002E8C7: 66 0F 38 DE 41 40  aesdec      xmm0,xmmword ptr [rcx+40h]
  000000018002E8CD: 66 0F 38 DE 41 50  aesdec      xmm0,xmmword ptr [rcx+50h]
  000000018002E8D3: 66 0F 38 DE 41 60  aesdec      xmm0,xmmword ptr [rcx+60h]
  000000018002E8D9: 66 0F 38 DE 41 70  aesdec      xmm0,xmmword ptr [rcx+70h]
  000000018002E8E6: 66 0F 38 DE 01     aesdec      xmm0,xmmword ptr [rcx]
  000000018002E8EB: 66 0F 38 DE 41 10  aesdec      xmm0,xmmword ptr [rcx+10h]
  000000018002E8FA: 66 41 0F 38 DF 02  aesdeclast  xmm0,xmmword ptr [r10]
  000000018003F458: 66 0F 38 DC E8     aesenc      xmm5,xmm0
  000000018003F45D: 66 0F 38 DC D8     aesenc      xmm3,xmm0
  000000018003F462: 66 0F 38 DC E0     aesenc      xmm4,xmm0
  000000018003F467: 66 0F 38 DC F0     aesenc      xmm6,xmm0
  000000018003F475: 66 0F 38 DD EF     aesenclast  xmm5,xmm7
  000000018003F47A: 66 0F 38 DD DF     aesenclast  xmm3,xmm7
  000000018003F47F: 66 0F 38 DD E7     aesenclast  xmm4,xmm7
  000000018003F492: 66 0F 38 DD F7     aesenclast  xmm6,xmm7

因此,在现代 Windows 上,您需要使用依赖于 bcryptprimitives.dll 的东西。我不知道 .Net 原语登记bcryptprimitives.dll


我还检查了 Windows 8.1 上的以下 DLL,并且不存在 AES-NI 指令:

  • advapi32.dll
  • bcrypt.dll
  • crypt32.dll
  • cryptbase.dll
  • cryptcatsvc.dll
  • cryptdlg.dll
  • cryptdll.dll
  • cryptext.dll
  • cryptnet.dll
  • cryptowinrt.dll
  • cryptsp.dll
  • cryptsvc.dll

Microsoft 网站上没有太多关于该主题的信息。我从csp "aes-ni" site:microsoft.com 获得了两次点击,csp "aesni" site:microsoft.com 获得了 0 次点击。无论发生什么,微软都会保密。

【讨论】:

  • 我能找到的最好的链是 .NET 加载 rsaenh(AesCryptoServiceProvider 加载“Microsoft Enhanced RSA and AES Cryptographic Provider”,这是我注册表中的 rsaenh.dll),这取决于 bcrypt.dll ,这取决于 bcryptprimitives.dll。如果我从 AesCryptoServiceProvider MSDN 页面复制/粘贴示例程序并“启用本机代码调试”,那么我确实会在“模块”窗口中看到 bcryptprimitives.dll。没试过在里面设置断点。
  • 是的,我可以在 .NET 中使用 VS 中的 aesenc 指令。对于使用 CBC 模式的 MSDN 示例,您希望在 bcryptprimitives 中使用 SymCryptAesCbcEncrypt,它要么调用使用 AES-NI 的 SymCryptAesCbcEncryptXmm,要么调用不使用 AES-NI 的 SymCryptAesCbcEncryptAsm
【解决方案3】:

我曾在最早具有这些功能的芯片组中工作。当时 Windows 7 不具备使用 AES 的能力。我求助于当时可用的 Ubuntu 并使用了英特尔文档,并通过一些内联程序集做了一个 cpuid。这符合我的培训目的。尽管如此,我学到的一件事是“英特尔安全密钥”几乎与“AES-NI”同时提供。因此,如果我在芯片组中发现 RDRAND 指令,这意味着我“可能”拥有 AES-NI。所以这种方式我能做的最简单的(但没有完全记录)是

//截至撰写本文时,PF_RDRAND_INSTRUCTION_AVAILABLE 尚未记录为 MSDN API 的一部分 IsProcessorFeaturePresent(PF_RDRAND_INSTRUCTION_AVAILABLE);

我们也可以通过这种方式使用 CPU 内部函数 https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=vs-2019

有关更多“证据”,另请参阅下面的文档。 https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp1894.pdf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 2017-10-07
    • 2012-09-20
    • 2014-05-28
    • 1970-01-01
    相关资源
    最近更新 更多