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

查看:129
本文介绍了获取临时密钥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#KeyDerivationFunction 没有强制返回原始密钥协议的选项,另请参见此处

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坐标,这是通过将另一侧的私钥与另一侧的公钥相乘而获得的,请参见椭圆曲线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 

在代码中,使用 GetKeyAgreementBC()生成Alice的原始密钥协议 keyAgreementAlice ,而使用生成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.

此外,当SHA256出现时,分别产生 ECDiffieHellmanCng#DeriveKeyMaterial()的(哈希)密钥协议,即 keyAgreementCngAlice keyAgreementCngBob 出于上述原因,从原始密钥协议生成了哈希,即分别为 keyAgreementSHA256Alice keyAgreementSHA256Bob .

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天全站免登陆