online murcielago encriptar desencriptar descifrar criptografia cifrar cifrado biblioteca archivos algoritmo java encryption rsa

murcielago - Cifrado RSA con clave pública dada(en Java)



cifrar y descifrar en java (4)

¿Su clave pública es realmente X509 codificada? Si no, entonces un Keyspec no codificado debería ayudar.

Estoy buscando una muestra de Java sobre cómo hacer el cifrado RSA con una clave pública dada (lo tengo en formato base64, parece que tiene una longitud de 1024 bits).

A continuación está mi código, pero tengo la excepción InvalidKeySpec.

String publicKey = "AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4a3jZJB2ewekgq2VgLNislBdql/glA39w0NjXZyTg0mW917JdUlHqKoQ9765pJc4aTjvX+3IxdFhteyO2jE3vKX1GgA3i3n6+sMBAJiT3ax57i68mbT+KAeP1AX9199aj2W4JZeP"; KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] res = new Base64Encoder().decode(publicKey.getBytes()); X509EncodedKeySpec KeySpec = new X509EncodedKeySpec(res); RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec); // here the exception occurs.. Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] cipherData = cipher.doFinal(input.getBytes()); return cipherData;

Por favor dame la muestra,


Así es como logro encriptar una cadena con solo una clave pública de RSA.

Primero guarde la clave pública en formato PEM con el nombre de archivo pubkey.pem

-----BEGIN PUBLIC KEY----- AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4... -----END PUBLIC KEY-----

Encuentre el módulo de clave RSA público

$ openssl rsa -pubin -in pubkey.pem -modulus -noout Modulus=F56D...

Encuentra la clave RSA pública Exponente

$ openssl rsa -pubin -in pubkey.pem -text -noout ... Exponent: 65537 (0x10001)

Luego insértelos en el siguiente código.

BigInteger modulus = new BigInteger("F56D...", 16); BigInteger pubExp = new BigInteger("010001", 16); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, pubExp); RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec); Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] cipherData = cipher.doFinal(text.getBytes());


Su "clave" no es una clave pública válida. Es una cadena de Base64 que, cuando se decodifica, produce una secuencia de 129 bytes, el primero es 0x00, seguido de 0x93. Este no es un formato válido para una clave pública RSA, pero sospechosamente se parece a la codificación firmada big-endian de un entero de 1024 bits (es decir, el tipo de codificación devuelta por BigInteger.toByteArray() y utilizada en ASN.1 "INTEGER " valores). Una clave pública RSA nominalmente consta de dos enteros, uno es el módulo y el otro es el exponente público . Un módulo RSA típico tiene una longitud de 1024 bits, por lo que es probable que tengas aquí el módulo. Aún necesita el exponente público para completar la clave.

X509EncodedKeySpec espera la codificación DER de una estructura ASN.1 que identifica el algoritmo como RSA y contiene una estructura codificada anidada que contiene los dos enteros para la clave pública RSA. Montar tal estructura a mano podría resultar difícil (es factible, pero requiere un conocimiento profundo de ASN.1). Un método más simple sería usar RSAPublicKeySpec :

String modulusBase64 = "..."; // your Base64 string here BigInteger modulus = new BigInteger(1, new Base64Encoder.decode(modulusBase64.getBytes("UTF-8"))); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec ks = new RSAPublicKeySpec(modulus, pubExp); RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);

En lo anterior, " pubExp " debería ser un BigInteger contenga el exponente público, que no se da. 3 y 65537 son los valores tradicionales para el exponente público, pero otros son posibles y no se proporciona suficiente información para discriminar entre exponentes públicos (es decir, su código parecerá funcionar incluso si no usa el correcto). Básicamente, solo tienes la mitad de la clave pública; deberías pedirle a quien te haya dado esa mitad que te envíe la otra mitad también.

Nota: String.getBytes() usa la codificación predeterminada de la plataforma, que no siempre es la misma. Si insiste en convertir una cadena en una secuencia de bytes, debe usar un nombre de "UTF-8" explícito, como "UTF-8" ; de lo contrario, puede tener problemas si su código se ejecuta alguna vez, por ejemplo, en un sistema ruso o chino. Además, no sé de dónde proviene la clase Base64Encoder (no es parte de la API Java estándar), pero es posible que también funcione directamente sobre una String o un StringReader , lo que hace innecesario el paso de conversión.


Su clave pública no se ve como un valor codificado en Base64 de 1024 bits. Un valor de 1024 bits requeriría 172 caracteres (el último es un relleno = ) y aquí tenemos 175 caracteres.

Para una prueba, reemplace los últimos cuatro caracteres en su Cadena con un único = y pruebe si esto elimina la excepción. Esto no resolverá el problema, pero puede apuntar en la dirección correcta.