Saltar al contenido

Obtener RSA privado key de PEM BASE64 Codificado privado key expediente

Te damos la bienvenida a nuestra web, en este lugar vas a encontrar la resolución de lo que estabas buscando.

Solución:

Acabas de publicar ese privado key, así que ahora todo el mundo sabe lo que es. Con suerte, eso fue solo para probar.

EDITAR: Otros han notado que el encabezado de texto openssl de la publicación key, —– BEGIN RSA PRIVATE KEY —–, indica que es PKCS # 1. Sin embargo, el contenido real de Base64 del key en cuestión es PKCS # 8. Evidentemente el OP copió y pegó el encabezado y el tráiler de un PKCS # 1 key en el PKCS # 8 key por alguna razón desconocida. El código de muestra que he proporcionado a continuación funciona con PKCS # 8 privado keys.

Aquí hay un código que creará el privado. key a partir de esos datos. Tendrá que reemplazar la decodificación Base64 con su decodificador IBM Base64.

public class RSAToy 

    private static final String BEGIN_RSA_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----n"
            + "MIIEuwIBADAN ...skipped the restn"
         // + ...   
         // + ... skipped the rest
         // + ...   
            + "-----END RSA PRIVATE KEY-----";

    public static void main(String[] args) throws Exception 

        // Remove the first and last lines

        String privKeyPEM = BEGIN_RSA_PRIVATE_KEY.replace("-----BEGIN RSA PRIVATE KEY-----n", "");
        privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
        System.out.println(privKeyPEM);

        // Base64 decode the data

        byte [] encoded = Base64.decode(privKeyPEM);

        // PKCS8 decode the encoded RSA private key

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privKey = kf.generatePrivate(keySpec);

        // Display the results

        System.out.println(privKey);
    

Este es el formato PKCS # 1 de un key. Prueba este código. No utiliza Bouncy Castle u otros proveedores de cifrado de terceros. Solo java.security y sun.security para el análisis de secuencias DER. También admite el análisis de un key en formato PKCS # 8 (archivo PEM que tiene un encabezado “—– BEGIN PRIVATE KEY —–“).

import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.Base64;

public static PrivateKey pemFileLoadPrivateKeyPkcs1OrPkcs8Encoded(File pemFileName) throws GeneralSecurityException, IOException 
        // PKCS#8 format
        final String PEM_PRIVATE_START = "-----BEGIN PRIVATE KEY-----";
        final String PEM_PRIVATE_END = "-----END PRIVATE KEY-----";

        // PKCS#1 format
        final String PEM_RSA_PRIVATE_START = "-----BEGIN RSA PRIVATE KEY-----";
        final String PEM_RSA_PRIVATE_END = "-----END RSA PRIVATE KEY-----";

        Path path = Paths.get(pemFileName.getAbsolutePath());

        String privateKeyPem = new String(Files.readAllBytes(path));

        if (privateKeyPem.indexOf(PEM_PRIVATE_START) != -1)  // PKCS#8 format
            privateKeyPem = privateKeyPem.replace(PEM_PRIVATE_START, "").replace(PEM_PRIVATE_END, "");
            privateKeyPem = privateKeyPem.replaceAll("\s", "");

            byte[] pkcs8EncodedKey = Base64.getDecoder().decode(privateKeyPem);

            KeyFactory factory = KeyFactory.getInstance("RSA");
            return factory.generatePrivate(new PKCS8EncodedKeySpec(pkcs8EncodedKey));

         else if (privateKeyPem.indexOf(PEM_RSA_PRIVATE_START) != -1)   // PKCS#1 format

            privateKeyPem = privateKeyPem.replace(PEM_RSA_PRIVATE_START, "").replace(PEM_RSA_PRIVATE_END, "");
            privateKeyPem = privateKeyPem.replaceAll("\s", "");

            DerInputStream derReader = new DerInputStream(Base64.getDecoder().decode(privateKeyPem));

            DerValue[] seq = derReader.getSequence(0);

            if (seq.length < 9) 
                throw new GeneralSecurityException("Could not parse a PKCS1 private key.");
            

            // skip version seq[0];
            BigInteger modulus = seq[1].getBigInteger();
            BigInteger publicExp = seq[2].getBigInteger();
            BigInteger privateExp = seq[3].getBigInteger();
            BigInteger prime1 = seq[4].getBigInteger();
            BigInteger prime2 = seq[5].getBigInteger();
            BigInteger exp1 = seq[6].getBigInteger();
            BigInteger exp2 = seq[7].getBigInteger();
            BigInteger crtCoef = seq[8].getBigInteger();

            RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);

            KeyFactory factory = KeyFactory.getInstance("RSA");

            return factory.generatePrivate(keySpec);
        

        throw new GeneralSecurityException("Not supported format of a private key");
    

El problema al que se enfrentará es que hay dos tipos de PEM formateados keys: PKCS8 y SSLeay. No ayuda que OpenSSL parezca usar ambos dependiendo del comando:

Lo normal openssl genrsa El comando generará un formato SSLeay PEM. Una exportación de un archivo PKCS12 con openssl pkcs12 -in file.p12 creará un archivo PKCS8.

El último formato PKCS8 se puede abrir de forma nativa en Java usando PKCS8EncodedKeySpec. SSLeay formateado keys, por otro lado, no se puede abrir de forma nativa.

Para abrir SSLeay privado keys, puede usar el proveedor BouncyCastle como muchos lo han hecho antes o Not-Yet-Commons-SSL ha tomado prestada una cantidad mínima de código necesario de BouncyCastle para admitir el análisis de PKCS8 y SSLeay keys en formato PEM y DER: http://juliusdavies.ca/commons-ssl/pkcs8.html. (No estoy seguro de si Not-Yet-Commons-SSL será compatible con FIPS)

Identificación de formato de clave

Por inferencia de las páginas de manual de OpenSSL, key los encabezados para dos formatos son los siguientes:

Formato PKCS8

No cifrado: -----BEGIN PRIVATE KEY-----

Cifrado: -----BEGIN ENCRYPTED PRIVATE KEY-----

Formato de SSLeay

-----BEGIN RSA PRIVATE KEY-----

(Estos parecen estar en contradicción con otras respuestas, pero he probado la salida de OpenSSL usando PKCS8EncodedKeySpec. Solo PKCS8 keys, mostrando ----BEGIN PRIVATE KEY----- trabajar de forma nativa)

Si te ha resultado de utilidad este artículo, nos gustaría que lo compartas con otros entusiastas de la programación así contrubuyes a dar difusión a esta información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *