【问题标题】:Windows CNG ECDH Secret Agreement structureWindows CNG ECDH 秘密协议结构
【发布时间】:2011-10-31 02:32:03
【问题描述】:

我花了几天时间搜索ECDH秘密协议的结构,但没有成功。我在 MSDN 中发现 NCryptSecretAgreement 函数设置了一个指向 NCRYPT_SECRET_HANDLE 变量的指针,该变量接收代表秘密协议值的句柄。我对 WinAPI 完全不熟悉,所以我只能阅读文档。

我需要在基于 Windows 的桌面应用程序和 Web 应用程序之间交换密钥。 我需要知道的是 CNG 的 KDF 究竟如何使用(在我的情况下是散列)秘密协议值。我使用 SHA-256 算法作为 KDF 并尝试对秘密的 X 和 Y 进行散列协议,但结果与 CNG 计算的一个不匹配。有什么想法吗?

谢谢。

【问题讨论】:

    标签: windows elliptic-curve diffie-hellman cng


    【解决方案1】:

    我无法保证 Microsoft 认为适合实施的内容,但 ECDH 上有一个名为 X9.63 的标准。在该标准中,ECDH 的工作方式如下:

    • 您运行 DH 事物,产生公共曲线点 (X, Y)(这是您从对等点获得的点,乘以您的秘密 DH 值)。

    • 您将 X(并且只有 XY 被丢弃)转换为我们称之为 Z。转换是无符号大端,并使用字段大小:如果 X 存在于字段 Fq 中,则转换正好产生 ceil(ceil(log q)/8)。例如。如果您使用 NIST P-521 曲线,您可以以素数 q 为模工作,即 2520521,所以 ceil(log q) = 521 并且生成的字节序列正好包含 66 个字节,无论 X 的值如何。用最常用的椭圆曲线(称为“P-256”),也就是32字节。

    • Z 派生为密钥,使用散列函数 H,其输出长度为 n 个字节(例如 n = 32 与 SHA-256),您计算可能无限的字符串 H1||H2||H 3||... 其中“||”表示串联,Hi = H(Z||i) 其中“i”使用大端约定表示为四个字节。简单来说,您将 Z 与一个 32 位计数器一起进行哈希处理,然后一次又一次地这样做,直到您有足够的字节来满足您的预期密钥长度。

    【讨论】:

    • 非常感谢您提供清晰而有用的答案。似乎 CNG 按照 X9.63 的定义计算它。我更改了代码,但现在还有另一个小问题:现在它有时有效,有时无效。但我只散列 Z 没有任何迭代和计数器。那是错误的方法,对吗?但是使用它,键有时会对应。我将 P256 与 SHA256 一起使用,因此哈希输出的大小与密钥的大小相同 - 32。在这种情况下,按照您描述的方式 (X.9.63),密钥是 H(Z||00||00||00| |01),对吗?迭代是否从 1 开始?还是0?我错过了什么吗?
    • 标准规定它应该是 H(Z||0x00||0x00||0x00||0x01)(计数器从 1 开始)。如果你得到一个带有 H(Z) 的“正确”键,即使只有一次,那么这证明 CNG 不符合标准。但还有别的。可能,CNG 将 X 编码为最小大小的 signed 序列(即第一个字节将清除其最高有效位;如有必要,将添加一个值 0x00 的额外字节)并对其进行哈希处理;它会匹配 H(Z) 大约一半的时间。
    • 根据您的回答,终于找到了 KDFs CNG 使用的东西。他们在这里:Microsoft Windows 7 Kernel Mode Cryptographic Primitives Library (cng.sys) Security Policy Document。但是问题仍然存在——我不能每次都匹配键。有时 H(Z) 有效,但大多数时候 - 无效。
    • 谢谢你,托马斯。最后,我把它弄出来了,现在键总是匹配的。你是对的,CNG 增加了额外的“0”字节。但是,它仅适用于 H(Z) 而不是 X9.63 定义的 H(Z||counter),尽管上述安全策略文档说 CNG 的 KDF 支持 FIPS 批准的 SP800-56A(第 5.8 节)、X9.63、和 X9.42 密钥派生。也许还有一些我错过了。
    猜你喜欢
    • 2016-09-23
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    相关资源
    最近更新 更多