#java #openssl #rsa
Вопрос:
У меня есть эта инструкция для проверки подписи с помощью OpenSSL
cat file_1 file_2 > data.bin
openssl dgst -sha1 -binary data.bin > data.bin.digest
openssl pkeyutl -verify -in data.bin.digest -inkey public.key -sigfile file.sign -pubin -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha1 -pkeyopt rsa_mgf1_md:sha1
Мне нужно реализовать эту инструкцию с помощью Java.
На данный момент я пытаюсь реализовать только последнюю команду, которая выполняет фактическую проверку, вот так:
Security.addProvider(new BouncyCastleProvider());
//public key
FileInputStream keyfis = new FileInputStream(keyPath);
byte[] encKey = new byte[keyfis.available()];
keyfis.read(encKey);
keyfis.close();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
//sign file
FileInputStream sigfis = new FileInputStream(signPath);
byte[] sigToVerify = new byte[sigfis.available()];
sigfis.read(sigToVerify);
sigfis.close();
//verification
sig = Signature.getInstance("SHA1withRSA/PSS");
sig.setParameter(new PSSParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, 32, 1));
sig.initVerify(pubKey);
byte[] dgst = FileUtils.readFileToByteArray(new File("C:\tmp\data.bin.digest"));
boolean verifies = sig.verify(dgst);
System.out.println("signature verifies: " verifies);
с помощью OpenSSL я получаю «Подпись успешно проверена», но Java возвращает «подпись проверена: ложь».
Чего мне не хватает в Java-коде?
Обновить
Исправленный код будет
//verification
sig = Signature.getInstance("SHA1withRSA/PSS");
sig.setParameter(new PSSParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, 234, 1));
sig.initVerify(pubKey);
byte[] file = FileUtils.readFileToByteArray(new File("C:\tmp\data.bin"));
sig.update(file, 0, file.length);
boolean verifies = sig.verify(sigToVerify);
System.out.println("signature verified: " verifies);
Комментарии:
1. В коде Java данные хэшируются неявно , т. е. вы должны передавать не хэш, а исходные данные ( data.bin ). Кроме того, данные передаются не внутрь
verify()
, а внутрьupdate()
. Вverify()
подписи передается. Размер соли, вероятно, также не составляет 32 байта. Обычно это соответствует размеру выходного дайджеста, т. е. 20 байт для SHA1. OpenSSL может использовать максимально допустимый размер соли:signature size - digest output size - 2 = 256 - 20 - 2
(в моем повторении это было так). Вы должны это проверить.2. @Topaco Да, это помогло! Спасибо!