提问者:小点点

获取临时键x和y坐标


使用。NET核心3.1,C#。

我不太擅长这种加密的东西。有人能帮我吗?

>

  • 如何获取新生成的临时公钥X和Y字节?[编辑:成功了!请参阅下面的代码]。

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

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

    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;
    }
    

  • 共1个答案

    匿名用户

    由于你已回答了第一个问题,所以我只回答第二个问题。

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

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

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

    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可以用于必要的计算。一种可能的实现是:

    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;
    }
    

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

    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())和导入公钥(例如使用重要的SubjectPublicKeyInfo())的步骤。当代码被执行时,例如以下输出结果:

    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的原始密钥协议keyAccementAlice是使用GetKeyConementBC()生成的,Bob的原始密钥协议keyConementBob是使用GetKeyConementExplite()生成的。两种实现的等价性通过两种变体返回相同的原始密钥协议这一事实来证明。

    此外,由于上述原因,ECDiffieHellmanCng#DeriveKeyContent()的(散列)密钥协议,即keyConementCngAlicekeyConementCngBob,分别从原始密钥协议生成SHA256散列,即keyConementSHA256AlicekeyConementSHA256Bob时产生。