I've got a string that's been encrypted by SJCL server-side, and needs to be decrypted in Android using whatever libraries are available. I tried BouncyCastle, until I ran into the problem of not being able to generate a key from PBKDF2. Now I'm using SpongyCastle, and I'm still running into issues. Here's my code so far for generating a key and decrypting the string:
private static byte[] decrypt(SecretKey key, byte[] encrypted, byte[] iv) throws Exception {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;
// Generate a 128-bit key
final int outputKeyLength = 128;
/*SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);*/
PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
generator.init(PBEParametersGenerator.PKCS5PasswordToBytes(passphraseOrPin), salt, iterations);
KeyParameter key = (KeyParameter) generator.generateDerivedMacParameters(outputKeyLength);
SecretKey secretKey = new SecretKeySpec(key.getKey(), "AES");
return secretKey;
}
Here's how I call it in my function:
char[] key = * put PBKDF2 password here *;
// Generate key from password
SecretKey decryptionKey = null;
try {
decryptionKey = generateKey(key, decodedObject.get("salt").getAsString().getBytes());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
byte[] decryptedTicketBytes = null;
// Decrypt the ticket
try {
decryptedTicketBytes = decrypt(decryptionKey, decodedObject.get("ct").getAsString().getBytes(), decodedObject.get("iv").getAsString().getBytes());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
The decodedObject is the string from SJCL after being run through a JsonParser with UTF-8 and being Base64 decoded. I took it and ran it through the SJCL Demo with the password and decrypted the string no problem. I must be missing something simple here.
There error I'm getting is on the cipher.doFinal step, and is as follows:
java.security.InvalidKeyException: nonce must have length from 7 to 13 octets
I don't think SJCL uses no padding on their cipher, so I tried using "AES/CCM/PKCS5Padding" on the getInstance but then got this error:
javax.crypto.NoSuchPaddingException: Only NoPadding can be used with AEAD modes.
TLDR: I'm looking for the easiest way to decrypt SJCL strings in Android. Suggestions would be appreciated.
Thanks!