I'm trying to encrypt/decrypt data using AES on Android and PHP side and recieving empty answer.
First, I generated symmetric key in Android:
public static SecretKeySpec generateSymmetric() {
// Set up secret key spec for 128-bit AES encryption and decryption
SecretKeySpec sks = null;
try {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed("any data used as random seed".getBytes());
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, sr);
sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
System.out.println("AES KEY: " + sks);
} catch (Exception e) {
Log.e(TAG, "AES secret key spec error");
}
return sks;
}
Then i convert SecretKeySpec to Base64 string format:
public static String ConvertSymmetricKeyToString(SecretKeySpec key) {
String symmetric_key = null;
symmetric_key = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
return symmetric_key;
}
Call the functions:
SecretKeySpec symmKey = generateSymmetric();
newSymmetricKeyString = CreateEncryptedXml.ConvertSymmetricKeyToString(symmKey);
Then i encrypt data using SecretKeySpec:
private static String encryptDataWithSymmetricKey (SecretKeySpec symmKey, String data) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
// encryption
byte[] toBeCiphred = data.getBytes("UTF-8");
String encryptedData = null;
try {
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, symmKey);
byte[] encodedBytes = c.doFinal(toBeCiphred);
System.out.println("BYTE STRING (ASYMM): " + encodedBytes);
encryptedData = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
} catch (Exception e) {
Log.e(TAG, "AES encryption error");
throw new RuntimeException(e);
}
return encryptedData;
}
encryptedData = encryptDataWithSymmetricKey(symmKey, text);
Then i pack string secret AES key and encrypted data (encrypted with this AES key) in XML and make POST request to php server using okhttp. String secret key is encrypted using RSA.
On the server side I tried to decrypt data. I can decrypt (from RSA) secret AES key and get it's string representation. On client (Android) and server side (PHP) it's the same. But how can i decrypt data using this string AES key? I tried this (PHP):
$encryptionMethod = "AES-128-CBC";
//$decryptedAESKey is an Android AES SecretKeySpec converted to string
//in Android the string key was base64_encoded, so i decode it
$secretHash = base64_decode($decryptedAESKey);
// Decrypt
$decryptedMessage = openssl_decrypt(base64_decode($encryptedData), $encryptionMethod, $secretHash);
//Result
echo "Encrypted: $encryptedData ";
echo " Decrypted: $decryptedMessage";
Result in php:
Encrypted: s/00eZdv6sMq1hIgPUMMknb1w8d03t+R5KHn5FkHqhNJyDlBZlbm8t+t4RWh9tg/7LD9R2VbihGG
Boz9ydMEszYGgTanE2TII+OOSFZIYgCU7ekKkRLax+F2yoMvSB52LDxQ9b9ZOTxy0Zn+hH6jbVdl
HVffbk+DJTJ1PVgeRfTaG4yC6cmXh5oFx7vDxM2u+8FWc3rNTt9zKUiu0FGLn3pWpA4wyCZfoCnA
rSJWrtaPLWxPEqipJCafTc1wRof9PqkDmIQJLOr84FpsnhH0JqjwXRmyDp5K8jKe+UzvE/B1B5Sj
QiTgK1Z2wPXzQClXimX2U9AQYc33FsYQMATHNw==
Decrypted:
What is wrong?
Cipher.getInstance("AES");
may result in different ciphers depending on the default security provider. It most likely results in"AES/ECB/PKCS5Padding"
, but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs. – Artjom B.