Надувной замок против Java RSA по умолчанию с OAEP - PullRequest
0 голосов
/ 11 мая 2018

Может кто-нибудь объяснить мне, почему этот код выбрасывает javax.crypto.BadPaddingException: Decryption error в последнюю строку при расшифровке ключа?

// Given an RSA key pair...
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

// ... and an AES key:
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
SecretKey aesKey = keyGenerator.generateKey();

// When I encrypt the key with this Bouncy Castle cipher:
Cipher encryptionCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC");
encryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedKey = encryptionCipher.doFinal(aesKey.getEncoded());

// Then trying to decrypt the key with this cipher...
Cipher decryptionCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
decryptionCipher.init(Cipher.DECRYPT_MODE, privateKey);
// ... throws `javax.crypto.BadPaddingException: Decryption error` here:
decryptionCipher.doFinal(encryptedKey);

Верно ли следующее утверждение из https://stackoverflow.com/a/27886397/66722 для RSA сOAEP?

"RSA / ECB / PKCS1Padding" на самом деле не реализует шифрование в режиме ECB.Он должен был называться «RSA / None / PKCS1Padding», поскольку его можно использовать только для шифрования одного блока открытого текста (или, действительно, секретного ключа).Это просто ошибка именования Sun / Oracle.

Если это так, я бы ожидал, что эти преобразования будут эквивалентны, и мой тест выше пройдёт.Одинаковое дополнение было указано в обоих случаях, так почему же BadPaddingException?

В любом случае, я был бы признателен непрофессионалу за объяснение разницы.

1 Ответ

0 голосов
/ 11 мая 2018

Подобные вопросы о Stackoverflow с дополнительной информацией см. В Maarten Bodewes ответы на , и , .

Часть «mode» строки преобразования не имеет никакого эффекта. Проблема в том, что разные провайдеры используют разные настройки по умолчанию. Это неудачно и совершенно определенно неоптимально. Должны ли мы обвинять Sun / Oracle? У меня нет мнения, кроме того, что я недоволен результатом.

OAEP - довольно сложная конструкция с двумя различными хеш-функциями в качестве параметров. Строка преобразования Cipher позволяет вам указать один из них, который вы указали как SHA-256. Однако функция MGF1 также параметризуется хеш-функцией, которую нельзя указать в строке преобразования шифра. По умолчанию провайдер Oracle - SHA1, а провайдер BouncyCastle - SHA-256. Таким образом, в действительности существует скрытый параметр, который имеет решающее значение для взаимодействия.

Решение состоит в том, чтобы более полно указать, что представляют собой эти скрытые параметры, предоставив OAEPParameterSpec для метода Cipher.init(...), как в следующем примере:

Cipher encryptionCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC");
OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1",
                MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
encryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpec);
// ...
// ...
// ...
Cipher decryptionCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1",
                MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
decryptionCipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParameterSpec);

Первый из них, по сути, запрещен, потому что это уже значения по умолчанию для Bouncycastle.

...