关于ECDiffieHellmanCng在.net framework 4.7中实现的秘密协议的问题?

时间:2017-10-13 17:56:04

标签: .net cryptography elliptic-curve

我有以下代码:

        var curve = ECCurve.NamedCurves.nistP256;
        var ecdhSender = ECDiffieHellman.Create(curve);
        var ecdhReceiver = ECDiffieHellman.Create(curve);

我的理解是,我应该能够通过使用ecdhReceiver.PublicKey使用ecdhSender对象或使用ecdhSender.PublicKey使用ecdhReceiver对象来计算秘密协议,并且两个秘密协议值应该相同。如果这是一个错误的假设,请告诉我。

由于ECDiffieHellman.Create返回ECDiffieHellman类型,我编写了以下代码以获取秘密协议:

        string receiverHexString = null;
        using (SafeNCryptSecretHandle secretAgreement = (ecdhReceiver as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhSender.PublicKey))
        {
            byte[] secretAgreementBytes = new byte[32];
            IntPtr pointer = secretAgreement.DangerousGetHandle();
            Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
            receiverHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
            Console.WriteLine($"receiver secretAgreement: 0x{receiverHexString}");
        }

        string senderHexString = null;
        using (SafeNCryptSecretHandle secretAgreement = (ecdhSender as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhReceiver.PublicKey))
        {
            byte[] secretAgreementBytes = new byte[32];
            IntPtr pointer = secretAgreement.DangerousGetHandle();
            Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
            senderHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
            Console.WriteLine($"sender secretAgreement: 0x{senderHexString}");
        }

        Assert.AreEqual(receiverHexString, senderHexString);

我的断言失败了。显然我做错了(如果秘密协议应该是相同的)。

我是如何从句柄中提取字节的?或其他什么?

1 个答案:

答案 0 :(得分:2)

last time I checked开始,没有记录的方法可以从CNG获取原始秘密协议值,这就是.NET不公开它的原因。

.NET中预期使用ECDH

"click_id and number"

还有

  • created_at and timestamp
  • ECCurve curve = ECCurve.NamedCurves.nistP256; // Usually you'll only have one private key (yours), so this isn't representative of // real code. An `ECDiffieHellman` object doesn't necessarily have a private key, // but an `ECDiffieHellmanPublicKey` object definitely doesn't. using (ECDiffieHellman bobPrivate = ECDiffieHellman.Create(curve)) using (ECDiffieHellman alicePrivate = ECDiffieHellman.Create(curve)) using (ECDiffieHellmanPublicKey bobPublic = bobPrivate.PublicKey) using (ECDiffieHellmanPublicKey alicePublic = alicePrivate.PublicKey) { byte[] ba = bobPrivate.DeriveKeyFromHash(alicePublic, HashAlgorithmName.SHA256); byte[] ab = alicePrivate.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256); // ba and ab have the same contents. }
  • DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] secretPrepend, byte[] secretAppend)
  • DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey)

如果bobPrivate和alicePublic(或者相反,alicePrivate和bobPublic)没有变化,那么提供相同的输入将产生相同的输出。

注意:如果可以的话,你应该避免具体谈论DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey, byte[] secretPrepend, byte[] secretAppend)。当ECDH最终进入.NET标准时,ECDHCng类不会。从.NET 4.6.2开始,一切都可以在基类上完成(除了打开持久化键);并且.NET Core倾向于不从其DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)工厂方法返回公共类型。