Существует ли стандартизированная кодировка фиксированной длины для открытых ключей EC?
Мне было интересно, существует ли (и я надеюсь, что есть) стандарт для размера открытого ключа для ECDH (алгоритм Диффи-Хеллмана эллиптической кривой) и ECDSA (алгоритм цифровой подписи эллиптической кривой) для каждого типа кривой над простыми полями (192, 224, 256) 384 и 521).
2 ответа
Если вы используете одну из "именованных кривых", тогда размер открытого ключа будет фиксированным и зависит от "размера поля" вашей базовой кривой.
Сжатое или несжатое представление
Размеры открытого ключа также зависят от того, используется ли "несжатое" представление или "сжатое" представление. В несжатой форме размер открытого ключа равен удвоенному размеру поля (в байтах) + 1, в сжатой форме - размеру поля + 1. Таким образом, если ваша кривая определена на secp256r1
(также называемый NIST P-256
или же X9.62 prime256v1
), то размер поля составляет 256 бит или 32 байта. И поэтому открытый ключ будет ровно 65 байтов (32*2 +1) в несжатом виде и 33 байта (32 +1) в сжатом виде.
Несжатая форма состоит из 0x04 (по аналогии с тегом STR OCTET STRING) плюс конкатенация двоичного представления координаты X плюс двоичное представление координаты y публичной точки.
Случай GF(2^p)
Если основным полем является GF(2^p), то x и y можно рассматривать как элементы из [0, n-1]. Они кодируются обычным образом, так как целые числа кодируются, а оставшееся пространство для заполнения точно log2(p)/8 байтов дополняется нулями.
Случай GF(2^m)
Для GF(2^m) x и y можно рассматривать как полиномы a_0x_0 + ... + a_m-1 с коэффициентами a_i 0 или 1. Их двоичное представление - это просто конкатенация коэффициентов.
дальнейшее чтение
Точные детали можно найти в SEC1v2. (Особенно в разделе 2.3.3 Преобразование эллиптической кривой в точку-октет-строковое на страницах 10 и 11.)
Я долго искал ответ и хотел поделиться своим на Java. Моя задача состояла в том, чтобы получить размер ключа от X509Certificate (веб-сайт, чтобы быть правильным)
Метод № 1 - фактически вычисление:
ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) certificate.getPublicKey();
int publicKeyLength = (ecPublicKey.getEncodedPublicValue().length - 1) / 2 * 8;
(Может быть добавлено подтверждение, если первый байт равен 0x04)
Способ № 2 - извлечение из некоторых "внутренних органов":
ECParameterSpec spec = ecPublicKey.getParams();
AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance("EC");
algorithmParameters.init(spec);
Provider provider = algorithmParameters.getProvider();
provider.get("KeyPairGenerator.EC KeySize");