ECDiffieHellman - mbedTLS против C # - PullRequest
       86

ECDiffieHellman - mbedTLS против C #

1 голос
/ 30 сентября 2019

Мне нужно использовать эллиптическую кривую Диффи-Хеллмана между ARM Cortex M3 и ПК. На ARM я использую mbed TLS . Со стороны ПК я хочу использовать C # и класс ECDiffieHellman (Cng) .

Я могу сделать ECDH на ARM против ARM, но у меня возникают проблемы, когда я пытаюсь заменить одинсторона с ПК.

  1. Проблемой стал обмен ключами. Я обнаружил, что ключ экспортируется mbed TLS как <LEN><0x04><X><Y>.

Таким образом, в C # я импортирую открытый ключ, используя

частный статический EC

DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
    var keyLength = 32;

    if (publicKey[0] != (2 + 2 * keyLength) - 1)
        throw new ArgumentException("Invalid key length", nameof(publicKey));
    if (publicKey[1] != 0x04)
        throw new ArgumentException("Invalid key format", nameof(publicKey));

    var parameters = new ECParameters()
    {
        Curve = ECCurve.NamedCurves.brainpoolP256r1,
        Q = new ECPoint()
        {
            X = publicKey.Skip(2).Take(keyLength).ToArray(),
            Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
        }
    };

    using (var tmp = ECDiffieHellman.Create(parameters))
    {
        return tmp.PublicKey;
    }
}
Для генерации ключа, который я пытался
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Tls;
ecdh.Seed = new byte[32];
ecdh.Label = Encoding.ASCII.GetBytes("ECDiffieHellman");

new RNGCryptoServiceProvider().GetBytes(ecdh.Seed);

// ...

var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);

Моя проблема в том, что сгенерированный общий секретный ключ имеет другую длину по сравнению с сгенерированным mbed TLS и не совпадает.

Кто-то уже решил эту проблему?

Спасибо!

РЕДАКТИРОВАТЬ 1:

Я забыл упомянуть, что я использую голый ECDH на ARM,Так что я не думаю, что есть какая-либо функция выполнения ключа. Достаточно ли хешировать (SHA256) результат, чтобы соответствовать стороне C # (при настройке SHA256 как KDF там)?

1 Ответ

0 голосов
/ 30 сентября 2019

Я решил проблему. Вкратце: просто хэшируйте результат ECDH.

C / C ++ сторона:

  1. EC Diffie Hellman
mbedtls_ecdh_init(...);
mbedtls_ecdh_setup(...);
mbedtls_ecdh_make_public(...); //make own public key and send it to peer
mbedtls_ecdh_read_public(...); //reed peers public key
mbedtls_ecdh_calc_secret(...); //note: i pass in my own RND func because of no OS
mbedtls_ecdh_free(...);
SHA256
mbedtls_sha256_init(...);
mbedtls_sha256_starts_ret(...);
mbedtls_sha256_update_ret(...);
mbedtls_sha256_finish_ret(...);
mbedtls_sha256_free(...);

C # сторона:

private void EllipticCurveDiffieHellman()
{
    var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);

    ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    ecdh.HashAlgorithm = CngAlgorithm.Sha256;

    //get relevant point from own public key
    var ownPublicKey = ecdh.PublicKey.ExportExplicitParameters().Q;

    var peersPublicKey = SendPublicKey(ownPublicKey); //key exchange
    var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);

    Console.WriteLine("Key: " + HexValue.Parse(sharedSecret.ToArray()));
}

DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
    var keyLength = 32;

    if (publicKey[0] != (2 + 2 * keyLength) - 1)
        throw new ArgumentException("Invalid key length", nameof(publicKey));
    if (publicKey[1] != 0x04)
        throw new ArgumentException("Invalid key format", nameof(publicKey));

    var parameters = new ECParameters()
    {
        Curve = ECCurve.NamedCurves.brainpoolP256r1,
        Q = new ECPoint()
        {
            X = publicKey.Skip(2).Take(keyLength).ToArray(),
            Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
        }
    };

    using (var tmp = ECDiffieHellman.Create(parameters))
    {
        return tmp.PublicKey;
    }
}
...