Encoding and decoding RSA using private key?

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){ /** Generate a new entry in the KeyStore by using the * KeyPairGenerator API. We have to specify the attributes for a * self-signed X.509 certificate here so the KeyStore can attach * the public key part to it. It can be replaced later with a * certificate signed by a Certificate Authority (CA) if needed. */ 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(); /* * Load the Android KeyStore instance using the the * "AndroidKeyStore" provider to list out what entries are * currently stored. */ 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(); } /* * Use a PrivateKey in the KeyStore to create a signature over * some data. */ 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?

+5
source share
2 answers

You are not using a public key for encryption.

If you use asymmetric encryption algorithms, you need to use the public key to encrypt your data and the private key only to decrypt it.

Besides encryption, you can also use the private key for signing, but this is not what you want here, so let's forget about it for now.

If you take the public key from the generated pair, when you encrypt your string and private key when decrypting, you should get the desired result. A public key that you can retrieve by accessing the certificate from the keystore containing your private key.

Alternatively, you can also use a symmetric algorithm such as AES, and thereby make your work a lot easier. In addition, symmetric algorithms are usually much faster, therefore asymmetric algorithms are never used exclusively, and in combination with symmetric algorithms, building the so-called hybrid algorithms.

+3
source

Signature generation is not the same as encryption. You need to encrypt with the public key and decrypt with the private key if you want to encrypt. If you want to generate a signature, you need to sign with the private key and verify using the public key. This order cannot be undone and cannot be mixed (reliably).

+1
source

Source: https://habr.com/ru/post/1203420/


All Articles