Использование ECDiffieHellmanCng для обмена ключами
Мы планируем использовать алгоритм ECDHE для обмена ключами между клиентом и сервером, чтобы оба они могли получить общий секретный ключ для шифрования сообщений.
Исходя из того, что я прочитал, чтобы использовать алгоритм ECDHE, обе стороны (клиент и сервер) должны сначала согласовать пару "общих" значений (p, g). Затем каждая сторона будет использовать закрытый ключ для генерации общего ключа, т.е. клиент использует закрытый ключ (P1) для генерации общего ключа (S1), а сервер использует закрытый ключ (P2) для генерации общего ключа (S2). Ссылка: [ https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
Общая ценность здесь относится к общей краске. Это на самом деле значение мода (p) и базовое значение (g), используемые обеими сторонами для генерации общих ключей.
Затем обе стороны обмениваются общими ключами (S1 и S2) и используют его со своим собственным закрытым ключом (P1 или P2) для получения общего секрета (K)
Когда я смотрю на примеры, которые используют ECDiffieHellmanCng для генерации ключей, я не вижу возможности указать эти "общие" значения где-либо. В нашем случае я ожидал, что и клиент, и сервер согласятся с p и g, а затем используют эти значения с "ECDiffieHellmanCng" для генерации общего общего ключа.
Я вижу, как Алиса и Боб создают новый экземпляр ECDiffieHellmanCng - они оба используют одни и те же общие значения (p и g)?
2 ответа
В своем вопросе вы ссылаетесь на статью, объясняющую (классика / МФК) Диффи-Хеллмана, которая является secret = (g ^^ (alice * bob)) % p
, Затем вы упоминаете ECDHE и спрашиваете о классе ECDiffieHellman(Cng) в.NET, который касается эллиптической кривой Диффи-Хеллмана... варианта ECC алгоритма IFC (целочисленная факторизационная криптография).
(IFC) У DH определенно есть проблема с выбором хорошего (g, p)
комбинация, и не быть обманутым человеком в середине. Для TLS серверная часть соединения получает все (g, p)
он хочет, а затем сообщает клиенту, что он выбрал, но клиент не может сказать, обманут ли он. Если у вас есть обе стороны, вы можете решить эту проблему, создав группу качества в 2048-битном пространстве и придерживаясь ее.
В.NET отсутствует поддержка (IFC) Диффи-Хеллмана, входящая в комплект поставки.
ECDH имеет другой набор параметров, которые в совокупности называются "кривая". Для простой кривой (наиболее распространенная форма) параметры являются кортежем (p, a, b, G, n, h)
(хотя на самом деле n
а также h
вычисления из (p, a, b, G)
), а затем математика ECC определяется поверх этого. Как только ECC математика определена, ECDH secret = X-Coordinate((alice * bob) * G)
, ECC имеет те же ловушки, что и (IFC) DH, выбор неправильных значений для параметров может позволить разыграть трюки на другой стороне. Из-за потенциальной хитрости и большого размера параметров домена выбор параметров домена стандартизируется в "именованные кривые". Два ключа на одной кривой по определению имеют одинаковый набор параметров домена. В TLS вам разрешено использовать только имя (ну, значение Object Identifier) кривой. Сервер в значительной степени может выбирать, какой набор параметров, но для максимальной совместимости обычно выбираются только три кривые (по состоянию на 2018 год): secp256r1
(он же NIST P-256), secp384r1
(он же NIST P-384) и secp521r1
(он же NIST P-521).
ECDiffieHellmanCng по умолчанию использует secp521r1
, но вы можете управлять кривой одним из трех способов:
Установка ecdh.KeySize
Изменение значения KeySize (установка его на любое значение, отличное от того, которое в данный момент хранится) приводит к генерации ключа на кривую этого размера. Это имело смысл для Windows 7, 8 и 8.1... потому что Windows CNG поддерживал только secp256r1
, secp384r1
, а также secp521r1
, Таким образом, вы можете установить KeySize на любой из { 256, 384, 521 }.
using (ECDiffieHellman ecdh = ECDiffieHellman.Create())
{
ecdh.KeySize = 384;
...
}
Создавая это таким образом
В Windows 10 добавлена поддержка большего количества кривых, и размеры стали неоднозначными. 256 значит secp256r1
или же brainpoolp256r1
(или же brainpoolp256t1
, numsp256t1
, secp256k1
...)? Ладно значит secp256r1
и существует более сложный API.
ECDiffieHellman.Create
фабрика перегружена (.NET Core 2.1+, .NET Framework 4.7+), которая принимает ECCurve
, Так что еще один способ создать кривую над secp384r1
было бы
using (ECDiffieHellman ecdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP384))
{
...
}
Это все еще может быть установлено позже
Может быть, вы используете DI и не можете использовать фабрику красиво. Ну, вы можете использовать GenerateKey
метод (.NET Core 2.1+, .NET Framework 4.7+) для достижения тех же результатов
using (ECDiffieHellman ecdh = ECDiffieHellman.Create())
{
ecdh.GenerateKey(ECCurve.NamedCurves.nistP384);
...
}
Есть и другие способы получения значений ECCurve, такие как ECCurve.CreateFromValue("1.3.132.0.34")
или просто вручную построить его из (p, a, b, G = (Gx, Gy), n, h)
,
- GF(q) обозначает конечное поле с q элементами
- р является базовой точкой
Да, они должны использовать ту же базовую точку и ту же эллиптическую кривую E над полем Fq. это общедоступные.