从 class ECDiffieHellmanCng 中提取共享密钥

Extract the shared secret from class ECDiffieHellmanCng

我目前正在开发一个 SSH 客户端,该客户端必须能够通过 ECDH KEX(NIST-256、384 和 521)与服务器交换密钥。

我做了一些(实际上很多)研究,找到了 .NET class ECDiffieHellmanCng,并且能够提取服务器的 public 密钥并将其导入到class。

但是,问题是我无法在不导出共享机密的情况下提取它 (ECDiffieHellmanCng.DeriveKeyMaterial(CngKey otherpartyPublicKey))。

有没有办法直接访问共享密钥("k" 在 RFC 文件中的称呼)?

Here 是 ECDH 实现的 RFC 中的第 7 页以及我需要共享密钥的原因:

The exchange hash H is computed as the hash of the concatenation of the following.

string V_C, client's identification string (CR and LF excluded)

string V_S, server's identification string (CR and LF excluded)

string I_C, payload of the client's SSH_MSG_KEXINIT

string I_S, payload of the server's SSH_MSG_KEXINIT

string K_S, server's public host key

string Q_C, client's ephemeral public key octet string

string Q_S, server's ephemeral public key octet string

mpint K, shared secret <-- this is why I need the pure secret before any derivation

感谢任何解决方案或提示!

即使经过大量研究我也找不到方法,所以答案是否定的 - 你无法提取秘密。

我的总体解决方案是完全放弃 ECDiffieHellmanCng class,而是用 C# 包装 OpenSSH 库。

希望这至少能对有相同想法的其他人有所帮助。

您实际上不需要 k,那么,您只需要计算 H。ECDiffieHellman class 允许您这样做。

byte[] prepend = Concat(V_C, V_S, I_C, I_S, K_S, Q_C, Q_S);
byte[] exchangeHash = ecdh.DeriveKeyFromHash(otherPublic, new HashAlgorithmName("whatever your hash algorithm is"), prepend, null);

虽然这是使用 .NET 4.6.2(目前处于预览阶段)API:DeriveKeyFromHash

如果您使用的是较旧的框架,它仍然可行,但需要专门使用 ECDiffieHellmanCng 类型:

ecdhCng.SecretPrepend = prepend;
ecdhCng.SecretAppend = null;
ecdhCng.HashAlgorithm = new CngAlgorithm("whatever your hash algorithm is");
ecdhCng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
byte[] exchangeHash = ecdhCng.DeriveKeyMaterial(otherPublic);