структура java openssl X509_SIG и функции кодирования / декодирования

#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. Большое спасибо Дейву за этот полный ответ. Это поможет мне двигаться вперед