Cifrado RSA Javascript y Descifrar Java

Pasé casi 2 días con diferentes combinaciones. Estoy generando un par de claves asimétricas (pública y privada) en java usando el algoritmo RSA y tratando de usar la clave pública en javascript para cifrar un texto y descifrarlo en java en el lado del servidor. Recibo la excepción “javax.crypto.IllegalBlockSizeException: los datos no deben superar los 128 bytes” al intentar descifrar la cadena cifrada en javascript. Agradecería alguna ayuda …

Usando la biblioteca de Javascript para cifrar.

https://github.com/wwwtyro/cryptico

var publicKeyString = “” // cadena de clave pública codificada en base64 codificada generada en java

Aquí está mi código javascript

var EncryptionResult = cryptico.encrypt("somestring", publicKeyString); console.log("Encrypted status-"+EncryptionResult.status); console.log("Encrypted String-"+EncryptionResult.cipher); 

Se está cifrando con éxito la cadena.

Generación y descifrado de claves Java

 Cipher cipher = Cipher.getInstance("RSA"); KeyFactory fact = KeyFactory.getInstance("RSA"); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); // 1024 used for normal KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); FileOutputStream fos = null; ObjectOutputStream oos = null; 

Código para almacenar la clave privada en el archivo que se utiliza para descifrar en el método de descifrado.

  RSAPrivateKeySpec rsaPrivKeySpec = fact.getKeySpec(privateKey, RSAPrivateKeySpec.class); System.out.println("Writing private key..."); fos = new FileOutputStream(PRIVATE_KEY_FILE); oos = new ObjectOutputStream(new BufferedOutputStream(fos)); oos = new ObjectOutputStream(new BufferedOutputStream(fos)); oos.writeObject(rsaPrivKeySpec.getModulus()); oos.writeObject(rsaPrivKeySpec.getPrivateExponent()); oos.close(); 

Método de descifrado

 public String decrypt(String ciphertext) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException { if (ciphertext.length() == 0) return null; byte[] dec = org.apache.commons.codec.binary.Base64.decodeBase64(ciphertext); try { System.out.println("Private Key file name----"+PRIVATE_KEY_FILE); privateKey = readPrivateKeyFromFile(PRIVATE_KEY_FILE); } catch (IOException e) { e.printStackTrace(); } cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decrypted = cipher.doFinal(dec); return new String(decrypted, PLAIN_TEXT_ENCODING); } //reading private key from file public PrivateKey readPrivateKeyFromFile(String fileName) throws IOException { FileInputStream fis = null; ObjectInputStream ois = null; try { fis = new FileInputStream(new File(fileName)); ois = new ObjectInputStream(fis); System.out.println("Private Key file-"+fileName); BigInteger modulus = (BigInteger) ois.readObject(); BigInteger exponent = (BigInteger) ois.readObject(); // Get Private Key RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent); KeyFactory fact = KeyFactory.getInstance("RSA"); PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec); return privateKey; } catch (Exception e) { e.printStackTrace(); } finally { if (ois != null) { ois.close(); if (fis != null) { fis.close(); } } } return null; } 

De la documentación de Cryptico parece que no es un simple cifrado RSA, sino una operación compleja que genera una clave AES, la cifra con RSA, cifra los datos con AES y genera una concatenación de la clave AES cifrada y los datos cifrados. Si desea descifrar eso en Java, tendrá que verificar el código fuente de Cryptico y Cryptico el mismo en Java.

En cuanto a su bash actual y javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes error:

Cuando no especifica la transformación completa, la transformación JCE predeterminada para RSA es RSA / ECB / PKCS1Padding .

En este modo, el RSA cifra o descifra un único bloque de datos cuya longitud no es mayor que el tamaño de la clave (más específicamente, si la secuencia de entrada de bytes se interpreta como un entero grande, su valor debe ser menor que el módulo utilizado por la RSA). Puede encontrar información adicional en esta y esta pregunta.

Con el tamaño de clave de 1024 bits, el tamaño máximo de datos es de 128 bytes, y eso es exactamente lo que dice la excepción porque la salida de Cryptico obviamente no es un solo bloque RSA y su longitud es mayor que la esperada por RSA “simple”. Tratar de usar algún otro modo de cifrado o modo de relleno en Java tampoco ayudará en esa situación.

Gracias Oleg por la información detallada. Definitivamente voy a echar un vistazo en él.

Por ahora me cambié a jsencrypt y parece funcionar bien.

https://github.com/travist/jsencrypt

EDITAR

¿Cómo se obtiene la clave pública codificada para el cifrado js?