Как я могу подписать необработанное сообщение (без предварительного хеширования) в Bouncy Castle?

Я работаю с библиотекой Bouncy Castle и не могу найти способ подписать необработанное сообщение без предварительного хеширования / заполнения. Я не уверен, какие параметры передать как alg.

При подписании дайджеста с заполнением PKCS v1.5 я использовал: «SHA1WithRSA», «SHA256WithRSA» и т. Д. (В соответствии с типом дайджеста).

signature = Signature.getInstance(alg, JCEProvider.CRYPTO_PROVIDER_NAME);

person user3698979    schedule 25.10.2016    source источник
comment
Подпись обычно определяется путем шифрования хэша сообщения закрытым ключом пользователя. Если по какой-либо причине вам не нужна хеш-часть, вы можете использовать свой стандартный алгоритм шифрования, но передать закрытый ключ вместо открытого. Однако имейте в виду, что это не сохраняет конфиденциальность или целостность сообщения. Этот метод обеспечивает только предотвращение отказа от авторства.   -  person CoconutBandit    schedule 25.10.2016
comment
То, что вы хотите, называется «подпись с восстановлением». См. Интерфейс SignerWithRecovery и реализующие классы.   -  person President James K. Polk    schedule 26.10.2016
comment
Примечание. Хеширование и заполнение разделены, и RSASSA-PKCS1-v1_5 включает кодирование ASN.1 с AlgorithmIdentifier плюс заполнение с 01 FF ... 00; см. rfc3447. В дополнение к прямому / «облегченному» API, предложенному @JamesKPolk, вы можете получить заполнение типа 01, но не кодировку ASN.1 через интерфейс поставщика с алгоритмом NoneWithRSA или просто RSA. Надежный провайдер также может выполнять PSS с различными хешами, а также без RSASSA-PSS RawRSASSA-PSS NoneWithRSASSA-PSS   -  person dave_thompson_085    schedule 26.10.2016
comment
Эх, я не понимаю. Вы можете сделать это, даже не используя Bouncy Castle. Почему это требование?   -  person Maarten Bodewes    schedule 30.10.2016


Ответы (2)


Signature signature = Signature.getInstance("NONEwithRSA","BC");

См. http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature.

person Francesca Merighi    schedule 18.07.2017
comment
Это неверный ответ. Вопрос задан для знака без хеширования или заполнения и "NONEwithRSA", безусловно, прокладок. - person Maarten Bodewes; 13.06.2018

Необработанное подписание - это не что иное, как модульное возведение в степень. Сейчас вроде бы есть два варианта, но в основном останется только один. Я объясню ниже.

Прежде всего, можно подумать, что использование Signature с "NoneWithRSA" должно работать. Алгоритм действительно существует, но, к сожалению, все еще работает; он просто удаляет структуру ASN.1 с указанием хэш-функции и значения. Так что этот недоступен.

Хотя подписание - это не то же самое, что шифрование, обе операции в конечном итоге полагаются на модульное возведение в степень. Так что, к счастью, можно использовать экземпляр Cipher для создания необходимых вам функций:

Security.addProvider(new BouncyCastleProvider());

Cipher rsa = Cipher.getInstance("RSA/ECB/NoPadding", BouncyCastleProvider.PROVIDER_NAME);
rsa.init(Cipher.DECRYPT_MODE, kp.getPrivate());
byte[] signatureUsingCipher = rsa.doFinal("owlstead"
        .getBytes(StandardCharsets.UTF_8));
System.out.println(Hex.toHexString(signatureUsingCipher));

Теперь следует отметить, что Bouncy Castle выполняет несколько иную операцию, чем поставщик Oracle SunJCE. Вместо того, чтобы просто удалить заполнение, он также забывает передать зашифрованный текст через алгоритм I2OSP (см. Стандарт PKCS # 1), который правильно кодирует выходной размер модуля. Таким образом, вы можете иметь зашифрованный текст меньшего размера, чем 128 байтов для определенных комбинаций ключа / открытого текста. Это очень легко увидеть, зашифровав значение 0, где на выходе будут нулевые байты.

Наконец, обратите внимание, что указание режима Cipher.ENCRYPT или Cipher.DECRYPT не имеет значения; оба просто выполняют модульное возведение в степень. Однако Cipher.DECRYPT с большей вероятностью ожидает закрытый ключ, поэтому я использовал его в приведенном выше коде.


Вы можете сгенерировать пару ключей для тестирования приведенного выше кода следующим образом:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();

Предупреждение: создание подписи без безопасного заполнения небезопасно; это может привести к атакам экзистенциальной подделки. Вы можете использовать это только как строительный блок для создания безопасной схемы.

person Maarten Bodewes    schedule 30.10.2016