如何让Tpm2.EcdhZGen()与NCrypt.DeriveKeyMaterialHash()生成匹配的Z值
解决.NET ECDiffieHellmanCng与TSS ECDH密钥派生对齐问题
核心对齐逻辑
要让两边生成一致的派生密钥,必须完全复刻.NET ECDiffieHellmanCng.DeriveKeyMaterial()的密钥派生流程,关键细节如下:
明确.NET的Z值定义
.NET的ECDiffieHellmanCng计算共享秘密时,仅取椭圆曲线共享点的X坐标作为原始Z值(而非X+Y的组合),这是多数人踩坑的核心点。复刻KDF流程
DeriveKeyMaterial()的默认行为为:派生密钥 = HASH(prepend字节 || Z值(X坐标) || append字节)- 默认prepend和append为空数组
- 默认HASH算法为SHA256(显式指定其他算法时需同步匹配)
Bob端(TSS框架)的具体实现步骤
针对Tpm2.EcdhZGen()返回的EccPoint类型,按以下步骤处理:
提取Z值原始字节
直接取EccPoint的x字段对应的字节数组:EccPoint.x.buffer就是共享点X坐标的原始大端字节(与.NET字节序一致)- 必须确保双方使用完全相同的椭圆曲线(如P-256的X坐标为32字节,P-384为48字节)
执行与.NET一致的HASH计算
默认场景(无prepend/append、SHA256)示例代码:// 从TSS的EccPoint获取X坐标字节 byte[] zRaw = eccPoint.x.buffer; // 计算SHA256哈希得到派生密钥 using (var sha256 = SHA256.Create()) { byte[] derivedKey = sha256.ComputeHash(zRaw); // 此结果与Alice端ECDiffieHellmanCng.DeriveKeyMaterial()完全一致 }
特殊场景适配
如果Alice端使用自定义参数,Bob端必须完全同步:
- 若指定了HASH算法(如SHA384):改用对应算法计算哈希
- 若传入了prepend/append字节:先拼接
prependBytes + zRaw + appendBytes,再计算哈希
验证方式
用同一组测试公私钥对分别在两边计算派生密钥,对比字节数组的十六进制值是否完全相同,即可确认对齐成功。
内容的提问来源于stack exchange,提问作者Hamish
相关产品推荐
相关产品推荐

