This is the tester:
public class CryptographySimpleTests extends ActivityTestCase
{
public void testsCryptographyClass_encryptAndDecrypt()
{
final String orgVal = "hi world! :D";
final String key = "key";
try
{
final byte[] encryptKey = Cryptography.deriveAES256Key(key);
final byte[] decryptKey = Cryptography.deriveAES256Key(key);
//Deviation method
Assert.assertTrue(Arrays.equals(encryptKey, decryptKey));
byte[] encrypted = Cryptography.encryptAES(encryptKey, orgVal.getBytes());
Assert.assertFalse(Arrays.equals(encrypted, orgVal.getBytes()));
byte[] decrypted = Cryptography.decryptAES(decryptKey, encrypted);
Assert.assertTrue(Arrays.equals(orgVal.getBytes(), decrypted));
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
}
}
Which fails because of the last assert:
Assert.fail(e.getMessage());
When trying to execute:
byte[] decrypted = Cryptography.decryptAES(decryptKey, encrypted);
Gives this stack trace:
javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
at com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:430)
at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:466)
at javax.crypto.Cipher.doFinal(Cipher.java:1340)
at bdevel.encuentralo.utils.Cryptography.decryptAES(Cryptography.java:59)
at bdevel.encuentralo.CryptographySimpleTests.testsCryptographyClass_encryptAndDecrypt(CryptographySimpleTests.java:32)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:115)
at junit.framework.TestResult.runProtected(TestResult.java:133)
at junit.framework.TestResult.run(TestResult.java:118)
at junit.framework.TestCase.run(TestCase.java:124)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
These are my functions:
public class Cryptography {
/**
* @param key AES Key
* @param inputValue Data to encrypt
* @return Can return null if something goes wrong
*/
public static byte[] encryptAES(byte[] key, byte[] inputValue)
throws NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException
{
SecretKeySpec sKeyS = new SecretKeySpec(key, "AES");
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, sKeyS);
}
catch (NoSuchAlgorithmException | InvalidKeyException i) {
cipher = null;
}
return cipher != null ? cipher.doFinal(inputValue) : null;
}
public static byte[] decryptAES(byte[] key, byte[] encryptedData)
throws NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException
{
SecretKeySpec sKeyS = new SecretKeySpec(key, "AES");
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, sKeyS);
}
catch (NoSuchAlgorithmException | InvalidKeyException i) {
cipher = null;
}
return cipher != null ? cipher.doFinal(encryptedData) : null;
}
private static byte[] deriveAES256KeySalt = null;
public static byte[] deriveAES256Key(String password)
throws InvalidKeySpecException, NoSuchAlgorithmException
{
/* Store these things on disk used to derive key later: */
int iterationCount = 1000;
int saltLength = 32; // bytes; should be the same size as the output (256 / 8 = 32)
int keyLength = 256; // 256-bits for AES-256, 128-bits for AES-128, etc
/* When first creating the key, obtain a salt with this: */
if(deriveAES256KeySalt == null) {
SecureRandom random = new SecureRandom();
deriveAES256KeySalt = new byte[saltLength];
random.nextBytes(deriveAES256KeySalt);
}
/* Use this to derive the key from the password: */
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), deriveAES256KeySalt, iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
return keyBytes;
}
}
If the assert that checks if the keys are the same works, why do I get that exception?
You are eating an java.security.InvalidKeyException: Illegal key size or default parameters
exception in your encryptAES
and decryptAES
methods. So don't eat them, either declare as throws
or promote to RuntimeException
.
Turns out you have two problems, for this reason, you can't do 256, but 128 solves that, then you are also requesting CBC
without an IvParameterSpec
(Which is causing java.security.InvalidKeyException: Parameters missing
). So supply that or change to ECB
:
public static byte[] encryptAES(byte[] key, byte[] inputValue)
throws NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec sKeyS = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, sKeyS);
return cipher.doFinal(inputValue);
}
public static byte[] decryptAES(byte[] key, byte[] encryptedData)
throws NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec sKeyS = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, sKeyS);
return cipher.doFinal(encryptedData);
}
Key length:
public static byte[] deriveAES256Key(String password)
throws InvalidKeySpecException, NoSuchAlgorithmException {
...
int keyLength = 128; // 256-bits for AES-256, 128-bits for AES
...
So I got it working like that, but step one is to stop eating the exception and you'll get better clues and probably work out on own.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With