0

I try to obtain a pair of key (public and private) to encrypt/decrypt text. For encryption no problems. For decryption I'va an error from one day and I don't understand why.

This is the relevant part of code:

    static void createKey(Context context) {
    try {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        Calendar start = Calendar.getInstance(Locale.ITALIAN);
        Calendar end = Calendar.getInstance(Locale.ITALIAN);
        end.add(Calendar.YEAR, 10);
        AlgorithmParameterSpec spec = null;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            spec = new KeyPairGeneratorSpec.Builder(context)
                    .setAlias(BuildConfig.APPLICATION_ID)
                    .setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
                    .setSerialNumber(BigInteger.ONE)
                    //.setStartDate(start.getTime())
                    //.setEndDate(end.getTime())
                    .build();
        } else {
            spec = new KeyGenParameterSpec.Builder(BuildConfig.APPLICATION_ID,KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setCertificateSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
                    .setDigests(KeyProperties.DIGEST_SHA256)
                    .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                    .setCertificateSerialNumber(BigInteger.valueOf(1337))
                    .setCertificateNotBefore(start.getTime())
                    .setCertificateNotAfter(end.getTime())
                    .setRandomizedEncryptionRequired(false)
                    .build();
        }
        kpg.initialize(spec);
        KeyPair kp = kpg.generateKeyPair();
        // END_INCLUDE(create_spec)
        Log.d(TAG, "createKey Public Key is: " + kp.getPublic());
        Log.d(TAG, "createKey Private Key is: " + kp.getPrivate());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
}


public static String encrypt(Context context, String text) {
    if(text == null || text.isEmpty()) {
        return null;
    }
    KeyStore keyStore = null;
    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        PublicKey publicKey = keyStore.getCertificate(BuildConfig.APPLICATION_ID).getPublicKey();

        Cipher input = getCipher();
        input.init(Cipher.ENCRYPT_MODE, publicKey);//, ivspec);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cipherOutputStream = new CipherOutputStream(
                outputStream, input);
        cipherOutputStream.write(text.getBytes("UTF-8"));
        cipherOutputStream.close();

        byte [] vals = outputStream.toByteArray();
        return Base64.encodeToString(vals, Base64.DEFAULT);
    } catch (Exception e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    return null;
}

public static String decrypt(Context context, String encryptedText) {
    KeyStore keyStore = null;
    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.Entry entry = keyStore.getEntry(BuildConfig.APPLICATION_ID, null);
        PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
        PublicKey publicKey = keyStore.getCertificate(BuildConfig.APPLICATION_ID).getPublicKey();

        Cipher output = getCipher();
        output.init(Cipher.DECRYPT_MODE, privateKey);//, ivspec);

        CipherInputStream cipherInputStream = new CipherInputStream(
                new ByteArrayInputStream(Base64.decode(encryptedText, Base64.DEFAULT)), output);
        ArrayList<Byte> values = new ArrayList<>();
        int nextByte;
        while ((nextByte = cipherInputStream.read()) != -1) {
            values.add((byte)nextByte);
        }

        byte[] bytes = new byte[values.size()];
        for(int i = 0; i < bytes.length; i++) {
            bytes[i] = values.get(i).byteValue();
        }

        return new String(bytes, 0, bytes.length, "UTF-8");

    } catch (Exception e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    return null;
}

static Cipher getCipher() throws Exception {
    return Cipher.getInstance("RSA/ECB/PKCS1Padding");
}

The exception is throwed when I call output.init(Cipher.DECRYPT_MODE, privateKey); in decrypt method and is:

05-17 16:52:02.334 31384-31384/ E/Utils: java.security.InvalidKeyException: Keystore operation failed
    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:733)
    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:754)
    at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
    at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
    at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977)
    at javax.crypto.Cipher.tryCombinations(Cipher.java:2884)
    at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:956)
    at javax.crypto.Cipher.init(Cipher.java:1199)
    at javax.crypto.Cipher.init(Cipher.java:1143)
    at it.a.b.utils.Utils.decrypt(Utils.java:249)
    at it.a.b.activities.LoginActivity.onCreate(LoginActivity.java:90)
    at android.app.Activity.performCreate(Activity.java:6910)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2746)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6577)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)
 Caused by: android.security.KeyStoreException: -65530
    at android.security.KeyStore.getKeyStoreException(KeyStore.java:672)
    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:754) 
    at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54) 
    at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89) 
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265) 
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109) 
    at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977) 
    at javax.crypto.Cipher.tryCombinations(Cipher.java:2884) 
    at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789) 
    at javax.crypto.Cipher.chooseProvider(Cipher.java:956) 
    at javax.crypto.Cipher.init(Cipher.java:1199) 
    at javax.crypto.Cipher.init(Cipher.java:1143) 
    at it.a.b.utils.Utils.decrypt(Utils.java:249) 
    at it.a.b.activities.LoginActivity.onCreate(LoginActivity.java:90) 
    at android.app.Activity.performCreate(Activity.java:6910) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2746) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864) 
    at android.app.ActivityThread.-wrap12(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567) 
    at android.os.Handler.dispatchMessage(Handler.java:105) 
    at android.os.Looper.loop(Looper.java:156) 
    at android.app.ActivityThread.main(ActivityThread.java:6577) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831) 

Have you any idea about this?

2
  • It would probably help to include a full stack trace. Also, which version of Android are you getting this error? Commented May 17, 2018 at 14:54
  • Thanks for reply James, I've edited my question including full stack trace. Commented May 17, 2018 at 15:01

1 Answer 1

0

It seems you creating key pair every time. Try try check key existence before you create them

if (!keyStore.containsAlias(ALIAS_RSA)) {
    createKeys();
} else {
    retrieveKeys();
}
Sign up to request clarification or add additional context in comments.

3 Comments

Already control it: if (!haveKey()) { createKey(context); if (!haveKey()) return null; } I've checked that call only first time createKey function Thanks for reply!
Take a look at setSignaturePaddings method. It seames it should be used only for signing/verifying developer.android.com/reference/android/security/keystore/…
use setEncryptionPaddings instead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.