android rsa public-key-encryption encryption

Descifrado de cifrado RSA en Android



public-key-encryption encryption (5)

Estoy implementando una demostración para encriptación y descifrado RSA en Android. Puedo realizar el cifrado muy bien, pero en el descifrado recibo una excepción: >>java.security.InvalidKeyException: unknown key type passed to RSA .

KeyPairGenerator kpg; KeyPair kp; PublicKey publicKey; PrivateKey privateKey; byte [] encryptedBytes,decryptedBytes; Cipher cipher,cipher1; String encrypted,decrypted; public String RSAEncrypt (final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); kp = kpg.genKeyPair(); publicKey = kp.getPublic(); privateKey = kp.getPrivate(); cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); encryptedBytes = cipher.doFinal(plain.getBytes()); encrypted = new String(encryptedBytes); System.out.println("EEncrypted?????"+encrypted); return encrypted; } public String RSADecrypt (final String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { cipher1=Cipher.getInstance("RSA"); cipher1.init(Cipher.DECRYPT_MODE, privateKey); decryptedBytes = cipher1.doFinal(result.getBytes()); decrypted = new String(decryptedBytes); System.out.println("DDecrypted?????"+decrypted); return decrypted; }

Y estoy llamando a la función desde aquí:

encrypt.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { try { RSAEncrypt rsaencrypt=new RSAEncrypt(); rsaencrypt.RSAEncrypt(name); result=rsaencrypt.RSAEncrypt(name); Toast.makeText(getBaseContext(), result.toString(),Toast.LENGTH_SHORT).show(); System.out.println("Result:"+result); } catch(Exception e) { e.printStackTrace(); Toast.makeText(getBaseContext(), e.toString(),Toast.LENGTH_LONG).show(); } } }); decrypt.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { { try { RSAEncrypt rsadecrypt=new RSAEncrypt(); rsadecrypt.RSADecrypt(result); ans=rsadecrypt.RSADecrypt(result); System.out.println("Result is"+ans); Toast.makeText(getBaseContext(), ans.toString(),Toast.LENGTH_LONG).show(); } catch(Exception e) { e.printStackTrace(); Toast.makeText(getBaseContext(), e.toString(),Toast.LENGTH_LONG).show(); System.out.println("Exception is>>"+e); } } });


Aquí hay un ejemplo para Android de:

  • generando un par de claves RSA privadas / públicas
  • Encriptar una cadena
  • descifrar la cadena encriptada

Estos métodos tratan con toda la codificación / decodificación de base 64.

public void TestEncryptData(String dataToEncrypt) { // generate a new public/private key pair to test with (note. you should only do this once and keep them!) KeyPair kp = getKeyPair(); PublicKey publicKey = kp.getPublic(); byte[] publicKeyBytes = publicKey.getEncoded(); String publicKeyBytesBase64 = new String(Base64.encode(publicKeyBytes, Base64.DEFAULT)); PrivateKey privateKey = kp.getPrivate(); byte[] privateKeyBytes = privateKey.getEncoded(); String privateKeyBytesBase64 = new String(Base64.encode(privateKeyBytes, Base64.DEFAULT)); // test encryption String encrypted = encryptRSAToString(dataToEncrypt, publicKeyBytesBase64); // test decryption String decrypted = decryptRSAToString(encrypted, privateKeyBytesBase64); } public static KeyPair getKeyPair() { KeyPair kp = null; try { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); kp = kpg.generateKeyPair(); } catch (Exception e) { e.printStackTrace(); } return kp; } public static String encryptRSAToString(String clearText, String publicKey) { String encryptedBase64 = ""; try { KeyFactory keyFac = KeyFactory.getInstance("RSA"); KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey.trim().getBytes(), Base64.DEFAULT)); Key key = keyFac.generatePublic(keySpec); // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); // encrypt the plain text using the public key cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encryptedBytes = cipher.doFinal(clearText.getBytes("UTF-8")); encryptedBase64 = new String(Base64.encode(encryptedBytes, Base64.DEFAULT)); } catch (Exception e) { e.printStackTrace(); } return encryptedBase64.replaceAll("(//r|//n)", ""); } public static String decryptRSAToString(String encryptedBase64, String privateKey) { String decryptedString = ""; try { KeyFactory keyFac = KeyFactory.getInstance("RSA"); KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey.trim().getBytes(), Base64.DEFAULT)); Key key = keyFac.generatePrivate(keySpec); // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); // encrypt the plain text using the public key cipher.init(Cipher.DECRYPT_MODE, key); byte[] encryptedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); decryptedString = new String(decryptedBytes); } catch (Exception e) { e.printStackTrace(); } return decryptedString; }


Creo que el problema es que debes usar el mismo par de claves para encriptar y descifrar el cifrado. En referencia a JavaDoc:

genKeyPair() This will generate a new key pair every time it is called.


En RSA, debe usar la clave pública para el cifrado y la clave privada para el descifrado.

El código de muestra utiliza para encriptar y desencriptar la clave pública; esto no puede funcionar.

Por lo tanto, en la parte de descifrado debe inicializar el cifrado de esta manera:

cipher1.init(Cipher.DECRYPT_MODE, privateKey);

Además, tu código tiene un segundo error importante:

Está convirtiendo una matriz de bytes con contenido binario en una Cadena.

¡Nunca convierta datos binarios a String!

Las cadenas son para caracteres de cadena, no datos binarios. Si desea empaquetar datos binarios en un String, codifíquelos para caracteres imprimibles, por ejemplo, usando Hex o Base64.

El siguiente ejemplo utiliza el codificador hexadecimal del paquete org.apache.common.codec : se debe instalar una biblioteca de terceros.

public byte[] RSAEncrypt(final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); kp = kpg.genKeyPair(); publicKey = kp.getPublic(); privateKey = kp.getPrivate(); cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); encryptedBytes = cipher.doFinal(plain.getBytes()); System.out.println("EEncrypted?????" + new String(org.apache.commons.codec.binary.Hex.encodeHex(encryptedBytes))); return encryptedBytes; } public String RSADecrypt(final byte[] encryptedBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { cipher1 = Cipher.getInstance("RSA"); cipher1.init(Cipher.DECRYPT_MODE, privateKey); decryptedBytes = cipher1.doFinal(encryptedBytes); decrypted = new String(decryptedBytes); System.out.println("DDecrypted?????" + decrypted); return decrypted; }


Mi clase:

package com.infovale.cripto; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; public class RSA { KeyPairGenerator kpg; KeyPair kp; PublicKey publicKey; PrivateKey privateKey; byte[] encryptedBytes, decryptedBytes; Cipher cipher, cipher1; String encrypted, decrypted; public String Encrypt (String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); kp = kpg.genKeyPair(); publicKey = kp.getPublic(); privateKey = kp.getPrivate(); cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); encryptedBytes = cipher.doFinal(plain.getBytes()); encrypted = bytesToString(encryptedBytes); return encrypted; } public String Decrypt (String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { cipher1=Cipher.getInstance("RSA"); cipher1.init(Cipher.DECRYPT_MODE, privateKey); decryptedBytes = cipher1.doFinal(stringToBytes(result)); decrypted = new String(decryptedBytes); return decrypted; } public String bytesToString(byte[] b) { byte[] b2 = new byte[b.length + 1]; b2[0] = 1; System.arraycopy(b, 0, b2, 1, b.length); return new BigInteger(b2).toString(36); } public byte[] stringToBytes(String s) { byte[] b2 = new BigInteger(s, 36).toByteArray(); return Arrays.copyOfRange(b2, 1, b2.length); } }


cuando usa el método RSAEcvypt, rellena PublicKey y clave privada. Y cuando descifras tu byte generado [], tu publicKey y privateKey son NULL. Por eso obtienes este error.

Debes usar tus claves estáticas;

enter code here KeyPairGenerator kpg; KeyPair kp; static PublicKey publicKey; static PrivateKey privateKey; byte [] encryptedBytes,decryptedBytes; Cipher cipher,cipher1; String encrypted,decrypted;