studio recuperar password example crear encryption android-keystore

encryption - recuperar - keystore java



java.lang.IllegalArgumentException: bad base-64 al desencriptar cadena (1)

Estoy intentando encriptar una cadena usando KeyStore y utilicé esta publicación como referencia.

Reemplazo de KeyPairGeneratorSpec con KeyGenParameterSpec.Builder equivalentes - Operación de Keystore fallida

sin embargo, sigo obteniendo esta "mala base-64" cuando desencripto la cadena. No estoy entendiendo exactamente cómo arreglar esto. Entiendo que la cadena cifrada contiene caracteres que el descifrador no conoce. Pero no entiendo la solución.

Vi algunas publicaciones como esas, pero no ayudó mucho ya que no hay ningún código en las respuestas.

java.lang.IllegalArgumentException: bad base-64

Este es un recorte de mi código de prueba, ¿alguien me puede mostrar cómo destripé mi cadena?

Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); inCipher.init(Cipher.ENCRYPT_MODE, publicKey); Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); outCipher.init(Cipher.DECRYPT_MODE, privateKey); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); cipherOutputStream.write(plainText.getBytes("UTF-8")); cipherOutputStream.close(); String ecryptedText = outputStream.toString(); Log.d(TAG, "Encrypt = " + ecryptedText); String cipherText = ecryptedText; CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 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(); } String finalText = new String(bytes, 0, bytes.length, "UTF-8"); Log.d(TAG, "Decrypt = " + ecryptedText);


Este es un ejemplo práctico de cómo puede usar Android KeyStore para cifrar / descifrar cadenas de memoria utilizando ByteArrayOutputStream y ByteArrayInputStream . Observe el cambio del proveedor, para >= 6 use "AndroidKeyStoreBCWorkaround" y para versiones anteriores use "AndroidOpenSSL" . Además, debe codificar los datos cifrados en la cadena Base64 utilizando Base64.encodeToString siguiente manera:

String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);

Mi último ejemplo de trabajo basado en tu código

try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); keyPairGenerator.initialize( new KeyGenParameterSpec.Builder( "key1", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) .build()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround"; Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); String plainText = "This is a text"; cipherOutputStream.write(plainText.getBytes("UTF-8")); cipherOutputStream.close(); String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); Log.d(TAG, "Encrypt = " + ecryptedText); String cipherText = ecryptedText; CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 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(); } String finalText = new String(bytes, 0, bytes.length, "UTF-8"); Log.d(TAG, "Decrypt = " + finalText); } catch (javax.crypto.NoSuchPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchAlgorithmException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchProviderException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidAlgorithmParameterException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidKeyException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnsupportedOperationException e) { Log.e(TAG, Log.getStackTraceString(e)); }

SALIDAS

D/MainActivity: Encrypt = rejkfeas3HgYnZOlC4S/R3KvlMTyiBjr5T6LqWGj9bq6nvpM0KBsoeYtr4OdCLITFX5GojuO4VpB Hy11n8zc9JcAx4IFW0Aw0/DfCmMDvIomQItBAaIWewZqNHc0UwS0y/JRhAe8SiTz5sFJ6Abvgax6 vEfbYT0gzok+qtlfBNQLPvXejquhc0pZBaX1RgKDZyEJh3DBVRaFDgogK8XphaI/xtd1Cww9uO63 QxA7HfrFUN8rJXrHF4EMi/yrDxs2xVHGF0v21xeuXRwLW9JXYn4fFAJJ0Jr8N5f03UDuKeNlI568 RFVOGH7WpOLvKN4CDlsC+DT4Z8YVIOdtS/tO+Q== D/MainActivity: Decrypt = This is a text

ACTUALIZAR

Para la API de Android 19 , solo tiene que usar la KeyStore API KeyPairGeneratorSpec lugar de KeyGenParameterSpec como esta:

try { Calendar start = Calendar.getInstance(); Calendar end = Calendar.getInstance(); end.add(Calendar.YEAR, 1); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this) .setAlias("key1") .setSubject(new X500Principal("CN=Sample Name, O=Android Authority")) .setSerialNumber(BigInteger.ONE) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); generator.initialize(spec); // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround"; KeyPair keyPair = generator.generateKeyPair(); Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); String plainText = "This is a text"; cipherOutputStream.write(plainText.getBytes("UTF-8")); cipherOutputStream.close(); String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); Log.d(TAG, "Encrypt = " + ecryptedText); String cipherText = ecryptedText; CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher); 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(); } String finalText = new String(bytes, 0, bytes.length, "UTF-8"); Log.d(TAG, "Decrypt = " + finalText); } catch (javax.crypto.NoSuchPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchAlgorithmException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchProviderException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidAlgorithmParameterException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidKeyException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnsupportedOperationException e) { Log.e(TAG, Log.getStackTraceString(e)); }