#java #openssl #cryptography #x509
#java #openssl #криптография #x509
Вопрос:
Я пытаюсь реализовать на Java алгоритм подписи, который я создал на C, который использует функцию openssl C API RSA_sign
. Эта функция не шифрует данные, а помещает данные в X509_SIG
структуру с некоторыми метаданными, кодирует структуру с помощью i2d_X509_SIG
функции openssl и затем, наконец, шифрует результат этого кодирования. Есть ли способ воспроизвести этот способ подписи данных с помощью Java? Существует ли X509_SIG
структура и функции кодирования / декодирования в какой-либо библиотеке Java? Yd
Ответ №1:
Вы неправильно описали (или неправильно поняли), что RSA_sign
делает.
Игнорируя некоторые особые случаи, не применимые здесь, он реализует схему подписи RSA, первоначально определенную в PKCS1 v1 как «тип 1», и теперь сохраненную в PKCS1 v2 как RSASSA-PKCS1-v1_5 (т. Е. Схему подписи RSA с приложением из версии v1.5 PKCS1); см. Раздел 8.2 и раздел 9.2 rfc8017, а также соответствующие примитивы в разделе 5.2. Для подписи (или как в RFC указано это более формально, для генерации подписи) это эффективно выполняет следующее, для того чтобы:
E1. хэшировать сообщение
E2. закодируйте значение хэша плюс идентификатор алгоритма для алгоритма хэширования как структуру ASN.1 DigestInfo в DER; из-за того, как работает DER, это эквивалентно добавлению фиксированного префикса, как описано в Примечаниях к разделу 9.2.
E3-5. добавьте 00 01 FF … (по мере необходимости, но не менее 8) 00
G2. преобразуйте строку октета в число, примените примитив RSASP1, который выполняет модульное возведение в степень с частным показателем, и преобразуйте (новое) число обратно в строку октета правильного размера. Исторически, поколение назад, это иногда описывалось как «шифрование с помощью закрытого ключа», а RSAVP1 аналогично как «дешифрование с помощью открытого ключа», хотя это семантически неверно, потому что подписание — это не шифрование, и вскоре было обнаружено, что эта путаница привела к плохим системным конструкциям, которые были уязвимы и сломаны, поэтому в этом столетии мы называем их подписыванием и проверкой.
RSA_sign
требуется, чтобы вызывающий объект выполнил этап хэширования (E1). Затем он вызывает encode_pkcs1
для выполнения шага E2, используя имя X509_SIG
для структуры, которая вызывается стандартно DigestInfo
. Затем он вызывает RSA_private_encrypt
, который выполняет E3-5 и G2; это название связано с тем, что OpenSSL происходит от SSLeay, который был написан десятилетия назад, когда путаница в отношении «подписи — это шифрование в обратном направлении» все еще была распространена.
Эта схема подписи является (1) стандартной и (2) очень распространенной и реализована в Java crypto — включая этап хэширования, предусмотренный стандартом, который отличается от OpenSSL RSA_sign
, и тот же самый этап DigestInfo. Смотрите java.security.Signature
названия алгоритмов (схемы) {SHA1,SHA256,etc}withRSA
в https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#signature-algorithms .
Комментарии:
1. Большое спасибо Дейву за этот полный ответ. Это поможет мне двигаться вперед