1

i am building an android apps that using fingerprint for the authentication, the source code of generating key and the cipher initialization for encryption in fingerprint authentication is like this (in FingerprintActivity).

public final void generateKey() {
    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
    } catch (Exception e) {
        e.printStackTrace();
    }

    KeyGenerator keyGenerator;
    try {
        keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
    } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
        throw new RuntimeException("Failed to get KeyGenerator instance", e);
    }

    try {
        keyStore.load(null);
        keyGenerator.init(new
                KeyGenParameterSpec.Builder(KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT |
                        KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(
                        KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setKeySize(256)
                .build());
        keyGenerator.generateKey();
    } catch (NoSuchAlgorithmException |
            InvalidAlgorithmParameterException
            | CertificateException | IOException e) {
        throw new RuntimeException(e);
    }
}

@TargetApi(Build.VERSION_CODES.M)
public boolean cipherInit() {
    try {
        cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new RuntimeException("Failed to get Cipher", e);
    }

    try {
        keyStore.load(null);
        SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                null);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return true;
    } catch (KeyPermanentlyInvalidatedException e) {
        return false;
    } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
        throw new RuntimeException("Failed to init Cipher", e);
    }
}

Then i want to reuse the generated key at another activity (HomeActivity, the activity after the fingerprint authentication succed) and i take the key like this.

private static final String KEY_NAME = "androidHive";
private KeyStore keyStore;
private Cipher cipher;
String test = "abc";
byte[] encryptedByte;

    TextView textView = (TextView) findViewById(R.id.test);

    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new RuntimeException("Failed to get Cipher", e);
    }

    try {
        keyStore.load(null);
        SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                null);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        encryptedByte = cipher.doFinal(test.getBytes());
    } catch (KeyPermanentlyInvalidatedException e) {
        textView.setText("A");
    } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
        throw new RuntimeException("Failed to init Cipher", e);
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
        textView.setText("C");
    }

I set the textview with some text to know what exception the program got, and i got it's illegal block size exception. Anyone know how to fix this ? Credits : AndroidHive (its where i get the code and i want to develop it further)

Artjom B.
  • 58,311
  • 24
  • 111
  • 196
  • 1
    what is the value of `KeyProperties.ENCRYPTION_PADDING_PKCS7`? If it is `PKCS7PADDING` as would be expected then your exception is impossible. Please edit your question to make it an [MCVE](KeyProperties.ENCRYPTION_PADDING_PKCS7). – President James K. Polk Aug 15 '17 at 13:33
  • Since you're using CBC mode, you need to save the IV after encryption in order to use the same IV for decryption. The IV is not supposed to be secret, but you need to use a random and unpredictable IV if you're encrypting multiple messages with the same key. Usually, the IV is prefixed to the ciphertext during encryption and sliced off before decryption. – Artjom B. Aug 15 '17 at 20:08
  • Check my answer here: https://stackoverflow.com/questions/42560868/storing-credentials-in-the-android-app/42716982#42716982 you have there a fully working code for encryption – Ricardo Aug 15 '17 at 20:12
  • i found out the answer guys, btw really thnks for your answer, the answer is i cant reuse the key that generated on the FingerprintActivity cause the kye is .setUserAuthenticationRequired(true) after i generate new key without .setUserAuthenticationRequired(true) with the same code, my program works well, hehehe, thnks by the way for your answer :) – Aswin Darma Saputra Aug 16 '17 at 08:06

0 Answers0