0
votes

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:754at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977at javax.crypto.Cipher.tryCombinations(Cipher.java:2884at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789at javax.crypto.Cipher.chooseProvider(Cipher.java:956at javax.crypto.Cipher.init(Cipher.java:1199at javax.crypto.Cipher.init(Cipher.java:1143at it.a.b.utils.Utils.decrypt(Utils.java:249at it.a.b.activities.LoginActivity.onCreate(LoginActivity.java:90at android.app.Activity.performCreate(Activity.java:6910at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2746at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864at android.app.ActivityThread.-wrap12(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567at android.os.Handler.dispatchMessage(Handler.java:105at android.os.Looper.loop(Looper.java:156at android.app.ActivityThread.main(ActivityThread.java:6577at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831

Have you any idea about this?

1
It would probably help to include a full stack trace. Also, which version of Android are you getting this error?President James K. Polk
Thanks for reply James, I've edited my question including full stack trace.benjaminbutton

1 Answers

0
votes

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();
}