Мы планируем использовать алгоритм ECDHE для обмена ключами между клиентом и сервером, чтобы оба могли получить общий секретный ключ для шифрования сообщений.
Основываясь на том, что я прочитал, для использования алгоритма ECDHE обе стороны (клиент и сервер) должны сначала согласовать пару «общих» значений (p, g). Затем каждая сторона будет использовать закрытый ключ для создания общего ключа, т.е. клиент использует закрытый ключ (P1) для создания общего ключа (S1), а сервер использует закрытый ключ (P2) для создания общего ключа (S2). Ссылка: [https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Description]
Под общим значением здесь понимается обычная краска. Фактически это значение мода (p) и базовое значение (g), используемые обеими сторонами для генерации общих ключей.
Затем обе стороны обмениваются общими ключами (S1 и S2) и используют их со своим собственным секретным ключом (P1 или P2) для получения общего секрета (K).
Когда я смотрю примеры, которые используют ECDiffieHellmanCng для генерации ключей, я не вижу возможности где-либо указать эти «общие» значения. В нашем случае я ожидал, что и клиент, и сервер согласятся по p и g, а затем будут использовать эти значения с «ECDiffieHellmanCng» для генерации общего общего ключа.
Я вижу, как Алиса и Боб создают новый экземпляр ECDiffieHellmanCng - используют ли они внутри одни и те же общие значения (p и g)?
Спасибо @bartonjs. Не могли бы вы подробнее объяснить, как задать для KeySize общие значения? Согласно документации, указание размера ключа (256/384/521) создает случайную пару ключей с использованием размера ключа. Достаточно ли использовать один и тот же размер ключей как на стороне клиента, так и на стороне сервера для генерации случайных пар ключей? Если мы обмениваемся этими открытыми ключами, а затем обе стороны получат секретный ключ, используя другой открытый ключ, будут ли они одинаковыми?
Ага. Это единственные три разрешенных числа.
Да, они должны использовать одну и ту же базовую точку и одну и ту же эллиптическую кривую E над полем Fq. они общедоступны.
Спасибо @kelalaka. У меня вопрос - где мы настраиваем эти значения в коде? Все, что мы делаем здесь, - это создаем новый экземпляр ECDiffieHellmanCng на стороне клиента и на стороне сервера. Что гарантирует, что оба используют одинаковые значения p и g?
Вы же распространяете код? поэтому укажите эти значения как для сервера, так и для клиента. Все должны согласовать параметры для обмена ключами.
В своем вопросе вы ссылаетесь на статью, объясняющую (классический / IFC) Диффи-Хеллмана, то есть secret = (g ^^ (alice * bob)) % p
. Затем вы упоминаете ECDHE и спрашиваете о классе ECDiffieHellman (Cng) в .NET, который касается эллиптической кривой Диффи-Хеллмана ... варианта ECC алгоритма IFC (Integer Factorization Cryptography).
(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 вам разрешено использовать только имя (ну, значение идентификатора объекта) кривой. Сервер в значительной степени может выбирать, какой набор параметров, но для максимальной совместимости обычно выбираются только три кривые (по состоянию на 2018 год): secp256r1
(он же NIST P-256), secp384r1
(он же NIST P-384) и secp521r1
( он же NIST P-521).
ECDiffieHellmanCng по умолчанию использует secp521r1
, но вы можете управлять кривой одним из трех различных способов:
Изменение значения 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)
.
p и g предназначены для IFC Diffie-Hellman, а не для ECC Diffie-Hellman. .NET не имеет общедоступного API для классического DH / IFC. Для ECDH вы выбираете общую кривую, о которой заботятся с помощью ECDiffieHellman.Create (ECCurve) (или установка KeySize для NIST P-256/384/521)