Как пересчитать симметричный ключ с реализацией ECDH в .net framework 4.7 и выше? - PullRequest
0 голосов
/ 04 июля 2018
  1. Сторона A имеет сертификат ECC (вместе с закрытым ключом)
  2. Сторона A отправляет этот сертификат ECC Стороне B
  3. Сторона B вычисляет ECDiffieHellmanPublicKey из этого сертификата

    var cert = new X509Certificate2(certBytes);
    var bytesWithFormatIndicator = cert.PublicKey.EncodedKeyValue.RawData;
    var bytesWithoutFormatIndicator = bytesWithFormatIndicator.Skip(1).ToArray();
    var preBytes = "45434b3120000000".HexToBytes();   // First 8 bytes are specific to elliptic curve P-256
    var rawBytes = bytesWithoutFormatIndicator;
    var fullBytes = new byte[preBytes.Length + rawBytes.Length];
    Buffer.BlockCopy(preBytes, 0, fullBytes, 0, preBytes.Length);
    Buffer.BlockCopy(rawBytes, 0, fullBytes, preBytes.Length, rawBytes.Length);
    
    ECDiffieHellmanPublicKey senderPublicKey = ECDiffieHellmanCngPublicKey.FromByteArray(fullBytes, CngKeyBlobFormat.EccPublicBlob);
    
  4. Сторона B создает реализацию ECDH (т. Е. Эфемерную пару открытого и закрытого ключей)

    var ecdhReceiver = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
    
  5. Сторона B, использованная выше для реализации ECDH, вместе с открытым ключом сертификата ECC Стороны A (и некоторыми байтами prepend и append) и вычисляет симметричный ключ

    var prependBytes = "00000001".HexToBytes();
    var appendBytes = "00000002".HexToBytes();
    var derivedSymmetricKey = ecdhReceiver.DeriveKeyFromHash(senderPublicKey, HashAlgorithmName.SHA256, prependBytes, appendBytes);
    
  6. Сторона B отправляет эфемерный открытый ключ (из вышеописанной реализации ECDH) Стороне A

    var ephemeralKeyBytesWithoutFormat = ecdhReceiver.PublicKey.ToByteArray().Skip(8).ToArray()
    
  7. Цель для Стороны А теперь состоит в том, чтобы вычислить тот же симметричный ключ, используя эфемерный открытый ключ Стороны В и сертификат ECC Стороны А (и его закрытый ключ).

Я застрял в (7). Любая помощь приветствуется.

Спасибо.

1 Ответ

0 голосов
/ 04 июля 2018

Это оказалось проще, чем я думал:

1) Сторона А может выгружать информацию о закрытых и открытых ключах из команды open ssl.

    openssl ec -in chris\key.pem -text -noout

2) Партия А получает вывод, который будет выглядеть следующим образом.

    Private-Key: (256 bit)
    priv:
        36:aa:94:67:66:2c:c5:3a:6b:44:da:af:2b:af:69:
        eb:83:e1:f6:b2:43:52:b5:b4:82:4f:bb:a7:64:71:
        68:3f
    pub:
        04:e7:b2:14:ce:a1:66:0a:2f:1f:3d:5e:af:95:be:
        e4:4b:00:27:fd:1a:06:f7:14:10:88:2a:ed:2c:51:
        1b:54:13:16:3e:05:f5:5b:bc:48:30:4a:49:32:46:
        7f:ca:fe:cc:b1:a0:09:91:6b:fd:8f:01:7f:41:ba:
        35:50:6e:a4:da
    ASN1 OID: prime256v1
    NIST CURVE: P-256

3) Сторона A создает реализацию ECDH с вышеуказанной информацией (начальный байт 0x04 в открытом ключе является индикатором формата, игнорируйте его):

    var ecParamsReceiver = new ECParameters
    {
        Curve = ECCurve.NamedCurves.nistP256,
        D = "36aa9467662cc53a6b44daaf2baf69eb83e1f6b24352b5b4824fbba76471683f".HexToBytes(),
        Q = new ECPoint()
        {
            X = "e7b214cea1660a2f1f3d5eaf95bee44b0027fd1a06f71410882aed2c511b5413".HexToBytes(),
            Y = "163e05f55bbc48304a4932467fcafeccb1a009916bfd8f017f41ba35506ea4da".HexToBytes(),
        }
    };
    ecParamsReceiver.Validate();
    var receiverEcdh = ECDiffieHellman.Create(ecParamsReceiver);

4) Сторона A создает открытый ключ Стороны B из эфемерного открытого ключа Стороны B

    var senderEphemeralPublicKey = ephemeralKeyBytesWithoutFormat;
    var ecParams = new ECParameters
    {
        Curve = ECCurve.NamedCurves.nistP256,
        Q = new ECPoint()
        {
            X = senderEphemeralPublicKey.Take(senderEphemeralPublicKey.Length / 2).ToArray(),
            Y = senderEphemeralPublicKey.Skip(senderEphemeralPublicKey.Length / 2).Take(senderEphemeralPublicKey.Length / 2).ToArray(),
        }
    };
    ecParams.Validate();
    var senderEcdh = ECDiffieHellman.Create(ecParams);

5) Сторона A использует одинаковые байты prepend и add для вычисления одного и того же симметричного ключа

    var prependBytes = "00000001".HexToBytes();
    var appendBytes = "00000002".HexToBytes();
    var derivedSymmetricKey = receiverEcdh.DeriveKeyFromHash(senderEcdh.PublicKey, HashAlgorithmName.SHA256, prependBytes, appendBytes);
...