Reputation: 11678
I'm using cipher to encrypt and decrypt messages:
public String encrypt(String string) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] stringBytes = string.getBytes("UTF-8");
byte[] encryptedBytes = cipher.doFinal(stringBytes);
return android.util.Base64.encodeToString(encryptedBytes, android.util.Base64.DEFAULT);
}
public String decrypt(String string) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] stringBytes = android.util.Base64.decode(string.getBytes(), android.util.Base64.DEFAULT);
byte[] decryptedBytes = cipher.doFinal(stringBytes);
return new String(decryptedBytes,"UTF-8");
}
For some reason although I'm using Base64 to encode and decode the string, I still get this error:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
What am I doing wrong?
Edit:
This is my JSONObject - I'm trying to decrypt the "m":
{"m":"Cu7FR2be0E6ZP2BrZaLU2ZWQSfycNg0-fPibphTIZno\r\n"}
The weird thing is that the error only appears in Android. My server is written in Java and I'm using Apache Base64 encoder and it works great.
Upvotes: 4
Views: 28109
Reputation: 18430
Your code seems OK to me, you can try to add "UTF-8" before decoding.
byte[] stringBytes = android.util.Base64.decode(string.getBytes("UTF-8"), android.util.Base64.DEFAULT);
EDIT
This is an example Security Utility class which do encryption/decryption that uses BouncyCastle and password-based AES encryption.
public class SecurityUtils {
public static final String KEY_DERIVATION_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String DELIMITER = "]";
private static final int KEY_LENGTH = 256;
private static final int ITERATION_COUNT = 1000;
private static final int SALT_LENGTH = 8;
private static SecureRandom random = new SecureRandom();
static {
Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
}
public static String encrypt(Context context, String plaintext)
throws Exception {
byte[] salt = generateSalt();
return encrypt(plaintext, getKey(salt, getPassword(context)), salt);
}
private static String encrypt(String plaintext, SecretKey key, byte[] salt)
throws Exception {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
byte[] iv = generateIv(cipher.getBlockSize());
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
if (salt != null) {
return String.format("%s%s%s%s%s",
new String(Base64.encode(salt)), DELIMITER, new String(
Base64.encode(iv)), DELIMITER, new String(
Base64.encode(cipherText)));
}
return String.format("%s%s%s", new String(Base64.encode(iv)),
DELIMITER, new String(Base64.encode(cipherText)));
} catch (Throwable e) {
throw new Exception("Error while encryption", e);
}
}
public static String decrypt(Context context, String ciphertext)
throws Exception {
return decrypt(ciphertext, getPassword(context));
}
private static String decrypt(String ciphertext, String password)
throws Exception {
String[] fields = ciphertext.split(DELIMITER);
if (fields.length != 3) {
throw new IllegalArgumentException("Invalid encypted text format");
}
try {
byte[] salt = Base64.decode(fields[0]);
byte[] iv = Base64.decode(fields[1]);
byte[] cipherBytes = Base64.decode(fields[2]);
SecretKey key = getKey(salt, password);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
byte[] plaintext = cipher.doFinal(cipherBytes);
String plainrStr = new String(plaintext, "UTF-8");
return plainrStr;
} catch (Throwable e) {
throw new Exception("Error while decryption", e);
}
}
private static String getPassword(Context context) {
return "My secret password";
}
private static SecretKey getKey(byte[] salt, String password)
throws Exception {
try {
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
ITERATION_COUNT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(
KEY_DERIVATION_ALGORITHM, "BC");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
return new SecretKeySpec(keyBytes, "AES");
} catch (Throwable e) {
throw new Exception("Error while generating key", e);
}
}
private static byte[] generateIv(int length) {
byte[] b = new byte[length];
random.nextBytes(b);
return b;
}
private static byte[] generateSalt() {
byte[] b = new byte[SALT_LENGTH];
random.nextBytes(b);
return b;
}
}
Upvotes: 5
Reputation: 6572
You need to convert Base-64 first.
CODEED = encrypt(Base64.encode(MYSTRING, Base64.DEFAULT));
MYSTRING = Base64.decode(decrypt(CODEED), Base64.DEFAULT);
here is a link http://androidcodemonkey.blogspot.com/2010/03/how-to-base64-encode-decode-android.html
Upvotes: 3