Почему Curve25519 правильно вычисляет пару ключей, даже если его параметры неверны?
Кажется, что.NET (Core 3.1) поддерживает настраиваемые кривые в ECC. Итак, я определил Curve25519 и сгенерировал пару ключей с помощью кода ниже:
using System;
using System.Security.Cryptography;
namespace Curve25519
{
class Program
{
static void Main(string[] args)
{
ECCurve ecCurve = new ECCurve() // Curve25519, 32 bytes, 256 bit
{
CurveType = ECCurve.ECCurveType.PrimeMontgomery,
B = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
A = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07, 0x6d, 0x06 }, // 486662
G = new ECPoint()
{
X = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 },
Y = new byte[] { 0x20, 0xae, 0x19, 0xa1, 0xb8, 0xa0, 0x86, 0xb4, 0xe0, 0x1e, 0xdd, 0x2c, 0x77, 0x48, 0xd1, 0x4c,
0x92, 0x3d, 0x4d, 0x7e, 0x6d, 0x7c, 0x61, 0xb2, 0x29, 0xe9, 0xc5, 0xa2, 0x7e, 0xce, 0xd3, 0xd9 }
},
Prime = new byte[] { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed },
//Prime = new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
Order = new byte[] { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed },
Cofactor = new byte[] { 8 }
};
using (ECDiffieHellman ecdhOwn = ECDiffieHellman.Create())
{
// generate the key pair
ecdhOwn.GenerateKey(ecCurve);
// save ECDiffieHellman implicit parameters including private key
ECParameters ecdhParamsOwn = ecdhOwn.ExportParameters(true);
// print key pair
Console.WriteLine(BitConverter.ToString(ecdhParamsOwn.D) + "\r\n" + BitConverter.ToString(ecdhParamsOwn.Q.X) + "\r\n" + BitConverter.ToString(ecdhParamsOwn.Q.Y));
}
}
}
}
Ниже приведен пример вывода:
90-54-A7-71-C0-03-D9-69-40-21-A4-CF-8C-81-7C-09-C4-CD-7A-44-77-2E-19-AD-B7-09-82-C9-AC-6E-AF-46
80-32-26-BD-C3-85-BC-35-17-98-B1-6C-C7-31-EF-BE-21-91-BA-CD-4A-BD-87-5B-FB-EC-4B-6B-02-C9-07-46
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
Затем я хотел провести перекрестную проверку с другой библиотекой / платформой, а именно x-cube-cryptolib/stm32f103c8. Учитывая закрытый ключ, сгенерированный ECDiffieHellman (1-я строка), управляющая библиотека вычислила тот же открытый ключ (2-я строка), проверив пару (ура).
Прежде чем перейти к этапу обмена ключами, я хотел поиграть с ним и изменил параметры Curve25519, как в закомментированном простом коде. Я ожидал увидеть ошибку или вычисление разных открытых ключей из одного и того же закрытого ключа двумя платформами. Но нет, ECDiffieHellman всегда рассчитывал пары ключей, которые подтверждаются управляющей библиотекой. Я изменил параметры кривой, чтобы они были неправильными, поменял местами или обнуил, и я сделал это для каждого параметра, очистил и перестроил проект, но случай всегда был одним и тем же. Даже когда я перешел к фазе обмена ключами, ECDiffieHellman вычислил тот же материал общего секретного ключа, что и контрольная библиотека.
Почему ECDiffieHellman/Curve25519 каким-то образом генерирует правильные пары ключей и общий секрет, которые согласованы с библиотекой управления, даже если его параметры определения неверны, по-видимому, игнорируя их? Или, может быть, речь идет о реализации ECDH.Net Core?
1 ответ
Я не знаю, какие библиотеки вы упомянули, но я знаю немного о
curve25519
.
ECDH - это, конечно, акт взятия точки открытого ключа двойника (на самом деле
k[G]
, где
k
их закрытый ключ (зажатый
256-bit
номер) и
G
является точкой генератора кривой) и умножая его на ваш закрытый ключ, получая
yourK * theirK * G
.
Этот процесс является коммутативным, поэтому он работает, когда аналог делает то же самое с вашим открытым ключом и своим закрытым ключом.
Теперь о том, почему параметры кривой вроде бы не имеют значения.
curve25519
представляет собой высокооптимизированную криптосистему с эллиптической кривой. Оптимизировано скалярное умножение (базовое скалярное умножение переменной, используемое для ECDH), оптимизирована точечная арифметика и т. Д. Умножение выполняется с использованием только
X-coordinate
и дифференциальные добавки. Подробности смотрите здесь.
X25519
(curve25519+ECDH) использует исключительно скалярное умножение "только по X", где точки представлены только их
X
координировать. Это один из самых быстрых и простых способов обмена ключами за постоянное время, постоянное время важно для временных атак по побочным каналам.
На самом деле кривая нужна только тогда, когда мы выполняем
EdDSA
точечная декомпрессия.
EdDSA
Формат провода точек складывается из координаты Y, а знак
X
координировать.
Дело не в том, что кривая игнорируется, конечно, операции с эллиптической кривой должны учитывать базовую кривую, над которой они работают, и действительно поле Галуа, над которым эта кривая определена, более того, что используемые вычисления гарантированно останутся на кривая по определению.
Если вы обнуляете все параметры, это странно, но если вы все еще покидаете поле (Prime
в вашем случае), как
2^255 - 19
, этого должно быть достаточно, чтобы класс ECDH знал, что делать.
Короче говоря, я думаю, что на самом деле уравнение кривой не используется в расчетах ECDH.