2014-09-06 2 views
0

У меня проблема с расшифровкой (или, может быть, неправильно шифрования, тоже) данных с RSA в Java. Я хочу шифрует открытый ключ еще некоторую информацию в строку, а затем расшифровать этот открытый ключ и шифрует с ней что-то (я использую 2048 RSA):Ошибка в расшифровке RSA Java данных: javax.crypto.BadPaddingException: дешифрование ошибка

Шифрование:

public void saveExportToFile(String fileName, BigInteger mod, BigInteger exp, String info, PublicKey puk) throws IOException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(baos)); 
    try { 
     oout.writeObject(mod); 
     oout.writeObject(exp); 
     oout.writeChars(info); 
     oout.close(); 
     baos.close(); 
     Cipher cipher = Cipher.getInstance("RSA"); 
     cipher.init(Cipher.ENCRYPT_MODE, puk); 

     FileOutputStream fos = new FileOutputStream(new File(fileName)); 
     BufferedOutputStream bos = new BufferedOutputStream(fos); 

     byte[] data = baos.toByteArray(); 

     int i = 0; 
     byte[] buffer = new byte[128]; 
     byte[] cipherData = null; 
     while (i < data.length) { 
      if (i+128 >= data.length) { 
       buffer = new byte[data.length - i]; 
       System.arraycopy(data, i, buffer, 0, data.length - i); 
       cipherData = cipher.doFinal(buffer); 
       bos.write(cipherData); 
      } else { 
       System.arraycopy(data, i, buffer, 0, 128); 
       cipherData = cipher.doFinal(buffer); 
       bos.write(cipherData); 
      } 
      i += 128; 
     } 

     bos.close(); 
    } catch (Exception e) { 
     throw new IOException("Unexpected error", e); 
    } 
} 

дешифрование:

public void getDataFromRSA(String sendname, PrivateKey privateKey) { 
    try { 
     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sendname))); 

     Cipher cipher = Cipher.getInstance("RSA"); 
     cipher.init(Cipher.DECRYPT_MODE, privateKey); 

     int length = 0; 
     int allLength = 0; 
     byte[] buffer = new byte[128]; 
     byte[] bufferAC = null; 
     byte[] outData = null; 
     byte[] allData = null; 
     byte[] tmpData = null; 
     while ((length = bis.read(buffer)) != -1) { 
      if (length < 128) { 
       bufferAC = new byte[length]; 
       System.arraycopy(buffer, 0, bufferAC, 0, length); 
       outData = cipher.doFinal(bufferAC); 
      } else { 
       outData = cipher.doFinal(buffer); // HERE IS THE ERROR 
      } 
      allLength += outData.length; 
      tmpData = allData; 
      allData = new byte[allLength]; 
      System.arraycopy(tmpData, 0, allData, 0, tmpData.length); 
      System.arraycopy(outData, 0, allData, tmpData.length, outData.length); 
     } 
    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException | InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } 
} 

EDIT ОК, мне кажется, я не знаю о шифровании столько, сколько я думал. Я бы хотел использовать только RSA (если это возможно), так как мне не нужно передавать информацию более одного раза (размер информации меняется). Я редактировал шифрования, как это:

int i = 0; 
byte[] buffer = new byte[245]; 
byte[] cipherData = null; 
while (i < data.length) { 
    if (i+245 >= data.length) { 
     buffer = new byte[data.length - i]; 
     System.arraycopy(data, i, buffer, 0, data.length - i); 
    } else { 
     System.arraycopy(data, i, buffer, 0, 245); 
    } 
    cipherData = cipher.update(buffer); 
    bos.write(cipherData); 
    i += 245; 
} 
bos.write(cipher.doFinal()); // HERE IS THE ERROR 
bos.close(); 

И теперь я получаю javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes (пробовал несколько меньшие значения для размера буфера). Это потому, что длина данных не кратно блокам? Может ли это быть исправлено? Спасибо за ответы.

+0

Вы не должны использовать RSA в качестве блочного шифрования. В вашей схеме злоумышленник может просто вставить предыдущий блок в любом месте вашего шифра, не заметив его во время дешифрования. Гибридное шифрование/дешифрование не так уж сложно, почему бы вам не сделать попытку сделать это правильно? –

+0

Для вашей текущей проблемы: у RSA есть накладные расходы, вы должны вложить не более 245 байтов и дешифровать на 256 байт (11 байт накладных расходов). Если необходимо, используйте doFinal в цикле с 245-байтовым буфером шифрования и буфером * для ввода * байта в 256 байт. Обратите внимание, что это не исправляет ваш протокол, а только вашу текущую реализацию. –

+0

Спасибо, я использую гибридную криптографию сейчас без проблем – d3im

ответ

3

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

Во-вторых, вы никогда не должны выполнять doFinal в цикле для одного сообщения. Используйте вместо этого update и один doFinal.

И в-третьих, 2048 бит равен 256 байт. Пока вы пытаетесь расшифровать 128 байтов вместо 256, вы получите это исключение. Обычно я использую 2048/Byte.SIZE, что делает код более читаемым и позволит избежать ошибок.

+0

Ты абсолютно прав. Спасибо, теперь я узнал что-то новое в криптографии Java. У меня есть только один вопрос: какие алгоритмы сохраняются для использования в простой Java (раньше я использовал BouncyCastle)? Я бы хотел что-то универсальное. Теперь я использую SHA-512, RSA 2048 и AES 128 (первый я попытался AES/ECB/PKCS5Padding, который я использовал с BouncyCastle, но он дал мне ошибку при дешифрования) – d3im

+0

То странный набор параметров. По крайней мере, вы должны использовать более крупный размер ключа для RSA, если вы хотите иметь постоянный уровень безопасности. См. Keylength.com. Никогда не используйте ECB. Если доступно, попробуйте GCM. OAEP будет хорошей идеей для RSA. –

0

Это исключение возникает при попытке шифрования данных с помощью секретного ключа и дешифрования с открытым ключом, вы должны изменить это, или вы должны использовать один ключ для шифрования и дешифрования данных. Это решило бы это исключение.

Смежные вопросы