获取临时密钥 x 和 y 坐标 [英] Get Ephemeral key x and y coordinates

查看:41
本文介绍了获取临时密钥 x 和 y 坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 .NET Core 3.1、C#.

Using .NET Core 3.1, C#.

我根本不擅长这种加密货币.有人可以帮我吗?

I'm not very good with this crypto stuff at all. Can someone help me?

  1. 如何获取新生成的临时公钥 X 和 Y 字节?.

  1. How do I obtain the newly generated ephemeral public key X and Y bytes? .

如何生成未散列的 DerivedKeyMaterial?也许这没有意义,但我被要求不要应用 ecdh.HashAlgorithm = CngAlgorithm.Sha256; 但 null 不是一个选项.

How do I generate a DerivedKeyMaterial that is not hashed? Maybe this doesn't make sense, but I was asked to not apply ecdh.HashAlgorithm = CngAlgorithm.Sha256; but null is not an option.

这是我目前正在做的获取 X 和 Y 字节的操作,但我认为这是错误的,因为当我在控制台中打印出来时,它与客户端生成的密钥不同.

This is what I am currently doing to grab X and Y bytes but I think it's wrong because when I print it out in console, it is different to the client's produced key.

public byte[] GetEphSecret(byte[] myPublicKey) {
    using var ecdh = new ECDiffieHellmanCng();

    ecdh.ImportSubjectPublicKeyInfo(myPublicKey, out _);
    ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;


    ecdh.HashAlgorithm = CngAlgorithm.Sha256;
    ecdh.GenerateKey(ECCurve.NamedCurves.nistP256);

    // 1. Obtain Ephemeral Key public x and y [Edit: Succesfully obtained with the following:]

    var x = ecdh.PublicKey.ExportParameters().Q.X;
    var y = ecdh.PublicKey.ExportParameters().Q.Y;
  
    CngKey cngKey = ImportEcPublicKey(myPublicKey);

    // 2. Is it possible to derive a Key that is not hashed?
    var derivedKey = ecdh.DeriveKeyMaterial(cngKey);
    return derivedKeyMaterial;
}

推荐答案

由于第一个问题已经由你自己回答了,所以我只解决第二个问题.

Since the first question has been answered by yourself in the meantime, I will only address the second question.

ECDiffieHellmanCng#DeriveKeyMaterial() 不返回原始密钥协议,而只返回从它派生的值.此外,所使用的函数是不可逆的,因此无法确定原始密钥协议.密钥派生的详细信息在 ECDiffieHellmanCng#KeyDerivationFunctionECDiffieHellmanCng#HashAlgorithm 属性.在发布的代码中,返回密钥协议的 SHA256 哈希值(ECDiffieHellmanKeyDerivationFunction.Hash, CngAlgorithm.Sha256).

没有强制返回原始密钥协议的选项,另见此处此处.因此,要确定原始密钥协议,除了使用其他库或从头重新计算密钥协议之外别无选择.

There is no option that forces the raw key agreement to be returned, see also here and here. Therefore, to determine the raw key agreement, there is no other choice than to use another library or to recalculate the key agreement from scratch.

关于第一个变体,BouncyCastle 是一个选项.一种可能的实现是:

Regarding the first variant, BouncyCastle is an option. One possible implementation is:

private static byte[] GetKeyAgreementBC(X9ECParameters ecParams, ECPoint publicKey, byte[] privateKey)
{
    ECDomainParameters eCDomainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N);
    Org.BouncyCastle.Math.EC.ECCurve curve = eCDomainParameters.Curve;
    
    Org.BouncyCastle.Math.EC.ECPoint pubKey = curve.CreatePoint(new BigInteger(1, publicKey.X), new BigInteger(1, publicKey.Y));
    BigInteger privKey = new BigInteger(1, privateKey);
    
    ECPublicKeyParameters ecPubKeyParams = new ECPublicKeyParameters("ECDH", pubKey, SecObjectIdentifiers.SecP256r1);
    ECPrivateKeyParameters ecPrivKeyParams = new ECPrivateKeyParameters(privKey, eCDomainParameters);
    
    IBasicAgreement basicAgreement = AgreementUtilities.GetBasicAgreement("ECDH");
    basicAgreement.Init(ecPrivKeyParams);
    byte[] keyAgreement = basicAgreement.CalculateAgreement(ecPubKeyParams).ToByteArrayUnsigned();
    return keyAgreement;
}

关于第二种变体,必须记住,一方的密钥协议是 EC 点的 X 坐标,它是通过将这一方的私钥与另一方的公钥相乘而获得的,参见Elliptic-curve Diffie-Hellman(使用椭圆的算法曲线).同样,BouncyCastle 可用于必要的计算.一个可能的实现是:

Regarding the second variant it has to be kept in mind that the key agreement of one side is the X coordinate of the EC point which is obtained by multiplying the private key of this side with the public key of the other side, see Elliptic-curve Diffie-Hellman (using the arithmetic of elliptic curves). Again, BouncyCastle can be used with respect to the necessary calculations. A possible implementation is:

private static byte[] GetKeyAgreementExplicit(X9ECParameters ecParams, ECPoint publicKey, byte[] privateKey)
{
    ECDomainParameters eCDomainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N);
    Org.BouncyCastle.Math.EC.ECCurve curve = eCDomainParameters.Curve;
    
    Org.BouncyCastle.Math.EC.ECPoint pubKey = curve.CreatePoint(new BigInteger(1, publicKey.X), new BigInteger(1, publicKey.Y));
    BigInteger privKey = new BigInteger(1, privateKey);
    
    Org.BouncyCastle.Math.EC.ECPoint keyAgreementECPoint = pubKey.Multiply(privKey).Normalize();
    byte[] keyAgreement = keyAgreementECPoint.XCoord.ToBigInteger().ToByteArrayUnsigned();
    return keyAgreement;
}

如前所述,两种实现在功能上是相同的,因此可以互换.可以使用以下代码进行测试:

As said, both implementations are functionally identical and therefore interchangeable. They can be tested with the following code:

using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Security.Cryptography;
...
using (var ecdhAlice = new ECDiffieHellmanCng())
using (var ecdhBob = new ECDiffieHellmanCng())
{
    // Generate Alice's private and public key
    ecdhAlice.HashAlgorithm = CngAlgorithm.Sha256;
    ecdhAlice.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    ecdhAlice.GenerateKey(ECCurve.NamedCurves.nistP256);
    byte[] privateKeyAlice = ecdhAlice.ExportParameters(true).D;
    ECPoint publicKeyAlice = ecdhAlice.ExportParameters(false).Q;

    // Generate Bob's private and public key
    ecdhBob.HashAlgorithm = CngAlgorithm.Sha256;
    ecdhBob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    ecdhBob.GenerateKey(ECCurve.NamedCurves.nistP256);
    byte[] privateKeyBob = ecdhBob.ExportParameters(true).D;
    ECPoint publicKeyBob = ecdhBob.ExportParameters(false).Q;

    // Alice's key agreement
    byte[] keyAgreementAlice = GetKeyAgreementBC(NistNamedCurves.GetByName("P-256"), publicKeyBob, privateKeyAlice);
    byte[] keyAgreementSHA256Alice = SHA256.Create().ComputeHash(keyAgreementAlice);
    byte[] keyAgreementCngAlice = ecdhAlice.DeriveKeyMaterial(ecdhBob.PublicKey);
    Console.WriteLine("Alice's raw key agreement (BC):        " + Hex.ToHexString(keyAgreementAlice));
    Console.WriteLine("Alice's hashed key agreement (BC):     " + Hex.ToHexString(keyAgreementSHA256Alice));
    Console.WriteLine("Alice's key agreement (.NET):          " + Hex.ToHexString(keyAgreementCngAlice));
    Console.WriteLine();

    // Bob's key agreement
    byte[] keyAgreementBob = GetKeyAgreementExplicit(NistNamedCurves.GetByName("P-256"), publicKeyAlice, privateKeyBob);
    byte[] keyAgreementSHA256Bob = SHA256.Create().ComputeHash(keyAgreementBob);
    byte[] keyAgreementCngBob = ecdhBob.DeriveKeyMaterial(ecdhAlice.PublicKey);
    Console.WriteLine("Bob's raw key agreement (explicit):    " + Hex.ToHexString(keyAgreementBob));
    Console.WriteLine("Bob's hashed key agreement (explicit): " + Hex.ToHexString(keyAgreementSHA256Bob));
    Console.WriteLine("Bob's key agreement (.NET):            " + Hex.ToHexString(keyAgreementCngBob));
    Console.WriteLine();
}

为简单起见,该示例省略了导出公钥(例如使用 ExportSubjectPublicKeyInfo())和导入(例如使用 ImportSubjectPublicKeyInfo())的步骤.当代码被执行时,例如输出结果如下:

For simplicity, the example omitted the steps where the public key is exported (e.g. with ExportSubjectPublicKeyInfo()) and imported (e.g. with ImportSubjectPublicKeyInfo()). When the code is executed, e.g. the following output results:

Alice's raw key agreement (BC):        d6f337d4c0d8e8bb34848d4f0c1c6834f66f69bbf9f284df5b87c7aee0584fc7
Alice's hashed key agreement (BC):     fb95a6b3b95d0882fa6796c28aa5f1a88d14c5b9a3f302b5deae50316cb7a273
Alice's key agreement (.NET):          fb95a6b3b95d0882fa6796c28aa5f1a88d14c5b9a3f302b5deae50316cb7a273

Bob's raw key agreement (explicit):    d6f337d4c0d8e8bb34848d4f0c1c6834f66f69bbf9f284df5b87c7aee0584fc7
Bob's hashed key agreement (explicit): fb95a6b3b95d0882fa6796c28aa5f1a88d14c5b9a3f302b5deae50316cb7a273
Bob's key agreement (.NET):            fb95a6b3b95d0882fa6796c28aa5f1a88d14c5b9a3f302b5deae50316cb7a273 

在代码中,Alice 的原始密钥协议 keyAgreementAlice 是用 GetKeyAgreementBC() 生成的,而 Bob 的原始密钥协议 keyAgreementBob 是用 生成的>GetKeyAgreementExplicit().两种实现的等效性体现在两个变体都返回相同的原始密钥协议这一事实.

In the code, Alice's raw key agreement keyAgreementAlice is generated with GetKeyAgreementBC() and Bob's raw key agreement keyAgreementBob is generated with GetKeyAgreementExplicit(). The equivalence of both implementations is shown by the fact that both variants return the same raw key agreement.

此外,ECDiffieHellmanCng#DeriveKeyMaterial() 的(散列)密钥协议,即 keyAgreementCngAlicekeyAgreementCngBob,分别是当 SHA256由于上述原因,散列,即 keyAgreementSHA256AlicekeyAgreementSHA256Bob 分别是根据原始密钥协议生成的.

Furthermore, the (hashed) key agreement of ECDiffieHellmanCng#DeriveKeyMaterial(), i.e. keyAgreementCngAlice and keyAgreementCngBob, respectively, results when the SHA256 hash, i.e. keyAgreementSHA256Alice and keyAgreementSHA256Bob, respectively, is generated from the raw key agreement, for the reasons stated above.

这篇关于获取临时密钥 x 和 y 坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆