RSA-дешифровка действительных данных дополняется ошибками (BadPaddingException) - PullRequest
2 голосов
/ 27 мая 2011

Я сталкиваюсь с очень специфической проблемой при использовании шифрования / дешифрования RSA в Java.

Пример кода:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();

Cipher enc = Cipher.getInstance("RSA");
enc.init(Cipher.ENCRYPT_MODE, kp.getPublic());
String CipherText = new String(enc.doFinal(PlainText.getBytes()));
System.out.println("CipherText: ") + CipherText);

Cipher dec = Cipher.getInstance("RSA");
dec.init(Cipher.DECRYPT_MODE, kp.getPrivate());
PlainText = new String(dec.doFinal(CipherText.getBytes()));
System.out.println("PlainText: " + PlainText);

Как все могут ясно видеть: я шифрую открытый текст, используя открытый ключ, после чего я дешифрую зашифрованный текст, используя закрытый ключ.

Этот код вылетает со следующим сообщением:

Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero

Я также пытался явно использовать «RSA / ECB / NoPadding», и это не удается в период декодирования. (Например, расшифрованный зашифрованный текст не совпадает с исходным открытым текстом).

И последнее, но не менее важное: я пытался выполнить это при использовании моей собственной функции заполнения PKCS1.5, в том числе спецификации PKCS1.5:

EMB = 00 || 02 || RD || 00 || MD
EMB - это закодированный блок сообщений длиной k
Где RD - 8 случайных ненулевых байтов
MD - это максимальная длина k = 11, и она может дополняться нулевыми байтами, чтобы получить длину EMB k.

После двух дней тестирования я могу только заключить, что алгоритм RSA в Java имеет недостатки или просто не выполняет то, что, как я ожидаю, будет работать.

Любые предложения или исправления в приведенном выше коде очень приветствуются, так как я полностью озадачен, почему приведенный выше код не будет просто работать должным образом.

1 Ответ

2 голосов
/ 27 мая 2011

Не делай этого:

String CipherText = new String(enc.doFinal(PlainText.getBytes()));

Две причины:

  • Это почти никогда хорошая идея для вызова String.getBytes() без указания кодировки. Вы действительно хотите, чтобы результат зависел от кодировки системы по умолчанию?
  • Определенно, никогда не рекомендуется рассматривать результат операции двоичного шифрования (т.е. непрозрачные двоичные данные) как закодированную строку. Вместо этого закодируйте его в Base64 или в шестнадцатеричном виде.

Вы можете использовать Кодек Apache Commons для выполнения операций кодирования / декодирования base64 или этот автономный кодер / декодер общественного достояния .

...