2016-12-15 3 views
-1

У меня возникает проблема, что я не уверен, что это исправление. Я использовал эту тему в качестве ссылки:java.io.IOException: ошибка при завершении шифрования при расшифровке подстрок

java.lang.IllegalArgumentException: bad base-64 when decrypting string

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

«java.io.IOException: Ошибка при доработке шифром»

в основном я разделить строку, как показано ниже:

static public class RSAString { 
    private ArrayList<String> mChunkList = new ArrayList<String>(); 
    RSAString() { 
     mChunkList.clear(); 
    } 
    public ArrayList<String> getChunkList() { 
     return mChunkList; 
    } 
    RSAString(String stringSrc) { 
     if (stringSrc.length() < CHUNK_SIZE) { 
      mChunkList.add(stringSrc); 
     } else { 
      int j = 0; 
      for (int i = 0; i < stringSrc.length()/CHUNK_SIZE; i++) { 
       String subString = stringSrc.substring(j, j + CHUNK_SIZE); 
       mChunkList.add(subString); 
       j += CHUNK_SIZE; 
      } 
      int leftOver = stringSrc.length() % CHUNK_SIZE; 
      if (leftOver > 0) { 
       String subString = stringSrc.substring(j, j + leftOver); 
       mChunkList.add(subString); 
      } 
     } 
    } 
} 

Тогда я дешифровать с этим кодом:

// This **DOES NOT** work 
final String AndroidOpenSSLString = "AndroidOpenSSL"; 
final String AndroidKeyStoreBCWorkaroundString = "AndroidKeyStoreBCWorkaround"; 
mProvider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? AndroidOpenSSLString : AndroidKeyStoreBCWorkaroundString; 
Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", mProvider); 
outCipher.init(Cipher.DECRYPT_MODE, mPrivateKey); 
for (String chunkEncrypted : rsaEcryptedText.getChunkList()) { 
    byte[] cipherText = chunkEncrypted.getBytes("UTF-8"); 
    CipherInputStream cipherInputStream = new CipherInputStream(
      new ByteArrayInputStream(Base64.decode(cipherText, Base64.NO_WRAP)), outCipher); 
    ArrayList<Byte> values = new ArrayList<>(); 
    int nextByte; 
    while ((nextByte = cipherInputStream.read()) != -1) { 
     values.add((byte) nextByte); 
    } 
    byte[] bytes = new byte[values.size()]; 
    for (int i = 0; i < bytes.length; i++) { 
     bytes[i] = values.get(i); 
    } 
    decryptedString += new String(bytes, 0, bytes.length, "UTF-8"); 
    cipherInputStream.close(); 
    cipherInputStream.reset(); 
} 

Единственная работа, которую я обнаружил, состояла в том, чтобы повторно инициализировать cypher каждую новую подстроку. Как и взлом ниже:

for (String chunkEncrypted : rsaEcryptedText.getChunkList()) { 
    // This works, but I am re-initializing the out cypher every time! 
    // super slow!!! WHY DO I HAVE TO DO THIS? 
    Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", mProvider); 
    outCipher.init(Cipher.DECRYPT_MODE, mPrivateKey); 
    byte[] cipherText = chunkEncrypted.getBytes("UTF-8"); 
    CipherInputStream cipherInputStream = new CipherInputStream(
      new ByteArrayInputStream(Base64.decode(cipherText, Base64.NO_WRAP)), outCipher); 
    ArrayList<Byte> values = new ArrayList<>(); 
    int nextByte; 
    while ((nextByte = cipherInputStream.read()) != -1) { 
     values.add((byte) nextByte); 
    } 
    byte[] bytes = new byte[values.size()]; 
    for (int i = 0; i < bytes.length; i++) { 
     bytes[i] = values.get(i); 
    } 
    decryptedString += new String(bytes, 0, bytes.length, "UTF-8"); 
    cipherInputStream.close(); 
    cipherInputStream.reset(); 
} 

Проблема с моим исправлением заключается в том, что дешифрование значительно замедляется. Кроме того, даже с моими подстроками при небольших размерах (подстрока int CHUNK_SIZE = 64) я получаю то же исключение.

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

и вот код шифрования - не уверен, если это имеет значение в данном случае - но она всегда работает:

Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", mProvider); 
inCipher.init(Cipher.ENCRYPT_MODE, mPublicKey); 
RSAString rsaStringPlainText = new RSAString(plainText); 
for (String chunkPlain : rsaStringPlainText.getChunkList()) { 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    CipherOutputStream cipherOutputStream = new CipherOutputStream(
      outputStream, inCipher); 
    cipherOutputStream.write(chunkPlain.getBytes("UTF-8")); 
    cipherOutputStream.flush(); 
    cipherOutputStream.close(); 
    byte[] ecryptedText = Base64.encode(outputStream.toByteArray(), Base64.NO_WRAP); 
    encryptedStringOut.mChunkList.add(new String(ecryptedText)); 
} 

ответ

1

RSA не подходит для массового шифрования, как это довольно медленно (более коэффициент 1000 по сравнению с AES). Вместо этого используйте симметричный алгоритм шифрования, например AES, если сможете. Если вам нужны два ключа RSA, используйте шифрование Hybrid, где вы шифруете данные случайным симметричным ключом, а затем шифруете этот ключ с помощью ключа RSA.

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

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