I am trying to encode and decode Strings on Android using the private key generated and saved using the Android Key Store device that was introduced in Android 4.3
I can successfully generate and get the private key using the following code:
private void generatePrivateKey(Activity context, String alias){ Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.YEAR, 1); Date end = cal.getTime(); KeyPairGenerator kpg = null; try { kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { e.printStackTrace(); } try { kpg.initialize(new KeyPairGeneratorSpec.Builder(context) .setAlias(alias) .setStartDate(now) .setEndDate(end) .setSerialNumber(BigInteger.valueOf(1)) .setSubject(new X500Principal("CN=" + alias)) .build()); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } KeyPair kp = kpg.generateKeyPair(); KeyStore ks = null; try { ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); Enumeration<String> aliases = ks.aliases(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } KeyStore.Entry entry = null; try { entry = ks.getEntry(alias, null); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnrecoverableEntryException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } if (!(entry instanceof KeyStore.PrivateKeyEntry)) { Log.w("E", "Not an instance of a PrivateKeyEntry"); } else{ Log.w("E", "Got Key!"); privateKeyEntry = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); } }
And here is the code that I use for encryption (encoding) and decryption (decoding):
private String encryptString(String value){ byte[] encodedBytes = null; try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); cipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry ); encodedBytes = cipher.doFinal(value.getBytes()); } catch (Exception e) { e.printStackTrace(); } return Base64.encodeToString(encodedBytes, Base64.DEFAULT); } private String decryptString(String value){ byte[] decodedBytes = null; try { Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); c.init(Cipher.DECRYPT_MODE, privateKeyEntry ); decodedBytes = c.doFinal(Base64.decode(value, Base64.DEFAULT)); } catch (Exception e) { e.printStackTrace(); } return new String(decodedBytes); }
Encryption works fine, but when I try to decrypt it, I get the following error:
javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
This seems to mean that the private key used for decryption is different from the one used for decryption, but in my code I use the same private key for both. I also saw that he suggested setting the key size manually, but do it in the KeyPairGenerator builder as follows:
.setKeySize(1024);
It does not work and seems to be available only in API 19, I need to configure API 18.
Can someone help me in the right direction regarding the solution?