问题
I generate a random IV, this IV is attached (in plain bytes) to front of the encrypted msg as shown below;
public String encrypt(String plainText, byte[] encryptionKey) throws Exception {
SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
cipher.init(Cipher.ENCRYPT_MODE, key, iV);
byte[] data = new byte[iV.getIV().length + plainText.getBytes("UTF-8").length];
// Merge together plain IV and encrypted cipher text
System.arraycopy(iV.getIV(), 0, data, 0, iV.getIV().length);
System.arraycopy(cipher.doFinal(plainText.getBytes("UTF-8")), 0, data, iV.getIV().length, plainText.getBytes("UTF-8").length);
return Base64.encodeToString(data, Base64.DEFAULT);
}
The message is sent between devices using WiFi Direct. This is handled in my MainActivity;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
crypto.iV = new IvParameterSpec(Arrays.copyOf(readBuf, 16));
// Construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, readMessage);
try {
String decryptMsg = crypto.decrypt(readMessage, SECRET_KEY);
// Present the message
(chatFragment).pushMessage("Buddy (decrypt): " + decryptMsg);
Log.d(TAG, decryptMsg);
} catch (Exception e) {
e.printStackTrace();
}
// Present the message (comment out after testing!)
//(chatFragment).pushMessage("Buddy (encrypt): " + readMessage);
break;
During decryption it fails with the warning;
04-04 14:55:05.770: W/System.err(9847): javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
04-04 14:55:05.789: W/System.err(9847): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:850)
04-04 14:55:05.790: W/System.err(9847): at javax.crypto.Cipher.doFinal(Cipher.java:1340)
04-04 14:55:05.790: W/System.err(9847): at com.example.cryptochat.Crypto.decrypt(Crypto.java:52)
04-04 14:55:05.790: W/System.err(9847): at com.example.cryptochat.MainActivity.handleMessage(MainActivity.java:463)
The problem lies in the decrypt method, i am however unsure on what i am doing wrong. That method is below;
public String decrypt(String cipherText, byte[] encryptionKey) throws Exception {
SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
cipher.init(Cipher.DECRYPT_MODE, key, iV);
String decrypt = new String(cipher.doFinal( Base64.decode(cipherText, Base64.DEFAULT)));
decrypt = new String(Arrays.copyOfRange(decrypt.getBytes(), 16, decrypt.getBytes().length));
return decrypt;
}
回答1:
When using a block cipher with padding the encrypted text is always larger that the decrypted text. But you only copy as many bytes as the decrypted text has into the message to be sent. Therefore your encrypted message is incomplete.
byte[] encryped = cipher.doFinal(plainText.getBytes("UTF-8"));
byte[] data = new byte[iV.getIV().length + encrypted.length];
System.arraycopy(iV.getIV(), 0, data, 0, iV.getIV().length);
System.arraycopy(encrypted, 0, data, iV.getIV().length, encrypted.length);
来源:https://stackoverflow.com/questions/29447412/java-android-decrypting-msg-with-iv-attached