ECIES: как правильно использовать ECDH-ввод для KDF? Эффект безопасности?
Чтобы полностью понять ECIES и использовать мою любимую библиотеку, я сам реализовал некоторые части ECIES. Выполнение этого и сравнение результатов привело к одному моменту, который для меня не совсем ясен: что именно вводит KDF?
Результатом ECDH является вектор, но что вы используете для KDF? Это просто значение X или X + Y (возможно, с добавлением 04)? Вы можете найти обе концепции в дикой природе, и для обеспечения взаимодействия было бы действительно интересно, какой путь является правильным (если вообще есть правильный путь - я знаю, что ECIEs - это скорее концепция и имеет несколько степеней свободы).
Объяснение (поправьте меня, если я ошибаюсь в конкретном пункте, пожалуйста). Если я говорю о длине байта, это будет относиться к ECIES с 256-битными ключами EC.
Итак, во-первых, общая картина: вот процесс ECIES, и я говорю о шаге 2 -> 3:
Открытый ключ получателя - это вектор V, эмпемический закрытый ключ отправителя - это скаляр u, а функция согласования ключей KA - это ECDH, которая по сути является умножением V * u. В результате вы получаете общий ключ, который также является вектором - назовем его "общий ключ".
Затем вы берете открытый ключ отправителя, объединяете его с общим ключом и используете его в качестве входных данных для функции получения ключа KDF.
Но: Если вы хотите использовать этот вектор для функции получения ключа KDF, у вас есть два способа сделать это:
- вы можете использовать только общий ключ X. Тогда у вас есть байтовая строка из 32 байтов.
- вы можете использовать X и Y общего ключа и добавить к нему 0x04 так же, как и открытые ключи. Тогда у вас есть строка байтов 01 + 32 + 32 байта [3) для завершения: вы также можете использовать X + Y как сжатую точку)
Длина байтовой строки на самом деле не имеет значения, потому что после KDF (который обычно включает хеширование) у вас всегда есть фиксированное значение, например 32 байта (если вы используете sha256).
Но, конечно, результат KDF будет совершенно другим, если вы выберете тот или иной метод. Возникает вопрос: как правильно?
- eciespy использует метод 2 https://github.com/ecies/py/blob/master/ecies/utils.py
- Криптография python возвращает только X в их ECDH: https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/. У них нет поддержки ECIES.
- если я правильно понимаю документацию CryptoC++, они также просто возвращают X: https://cryptopp.com/wiki/Elliptic_Curve_Diffie-Hellman
- то же самое с Java BountyCastle, если я правильно это прочитал - результат будет целым числом: https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
- но вы также можете найти онлайн-калькуляторы с обоими X и Y: http://www-cs-students.stanford.edu/~tjw/jsbn/ecdh.html
Итак, я попытался получить больше информации в документации:
- есть поддержка ISO для ECIES. Они не описывают это подробно (или мне не удалось его найти), но я бы интерпретировал это как способ с полным вектором, X и Y: https://www.shoup.net/papers/iso-2_1.pdf
- есть этот документ, на который есть множество ссылок в Интернете и который относится к простому использованию X на странице 27: http://www.secg.org/sec1-v2.pdf
Итак, результат: я запутался. Может ли кто-нибудь указать мне правильное направление, или это просто степень вашей свободы (и повод для большого удовольствия, когда дело касается совместимости)?
1 ответ
Отвечу на свой вопрос сам: да, это степень свободы. Координата X называется компактным представлением и определена в RFC 6090. Так что оба действительны.
Они также одинаково безопасны, потому что вы можете вычислить Y из X, как описано в приложении C в RFC 6090.
По умолчанию используется компактное представление. Оба способа несовместимы друг с другом, поэтому, если вы столкнетесь с проблемами совместимости между библиотеками, это может быть интересным моментом для выяснения.