2010-10-27 34 views
10

tener una cadena que se envía desde el siguiente formato:¿Cómo podemos convertir una cadena de PEM a Der formato

-----BEGIN RSA PUBLIC KEY----- 
MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY 
mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma 
XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED 
-----END RSA PUBLIC KEY----- 

¿Cómo puedo construir un objeto PublicKey de esta cadena? han tratado el siguiente eliminar la cabecera y el pie de página y base 64 decodifican el buffer

public static PublicKey getFromString(String keystr) throws Exception 
    { 
    //String S1= asciiToHex(keystr); 
    byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(keystr); 
    X509EncodedKeySpec spec = 
     new X509EncodedKeySpec(keyBytes); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    return kf.generatePublic(spec); 

    } 

Esta falla ya sea como un formato de clave no válida o conseguirá debajo de error se está generando

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence 
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188) 
at java.security.KeyFactory.generatePublic(KeyFactory.java:304) 
at PublicKeyReader.getFromString(PublicKeyReader.java:30) 
at Tst.main(Tst.java:36) 

La clave excelentes referencias del API de openSSL PEM_write_bio_RSAPublicKey(bio, rsa);

+0

han utilizado el enlace .Pero no hará el converstion der formato – MSSV

+0

Tenga en cuenta que lo que está tratando de hacer no es realmente una "conversión a DER". Convertir a DER es simplemente decodificar lo que es base64 aquí y sacarlo como una secuencia de bytes. Está intentando decodificar la estructura ASN.1. – Bruno

Respuesta

9

llamando al PEM_write_bio_RSAPublicKey, solo el módulo de clave y el exponente público se codifican en los datos PEM de salida. Sin embargo, el X509EncodedKeySpec Se espera que este ASN.1 Formato clave:

SubjectPublicKeyInfo ::= SEQUENCE { 
    algorithm AlgorithmIdentifier, 
    subjectPublicKey BIT STRING } 

Se debe utilizar la función de PEM_write_bio_PUBKEY que codifica la clave pública utilizando la estructura SubjectPublicKeyInfo el que como era de esperar por X509EncodedKeySpec

Otra solución posible decodificar la llave. Por desgracia, no creo que sea posible hacer sólo con la API de JDK estándar, pero se puede hacer con la Bouncycastle biblioteca

import org.bouncycastle.asn1.*; 
import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; 

public static PublicKey getFromString(String keystr) throws Exception 
{ 
    //String S1= asciiToHex(keystr); 
    byte[] keyBytes = new sun.misc.BASE64Decoder().decodeBuffer(keystr); 
    ASN1InputStream in = new ASN1InputStream(keyBytes); 
    DERObject obj = in.readObject(); 
    RSAPublicKeyStructure pStruct = RSAPublicKeyStructure.getInstance(obj); 
    RSAPublicKeySpec spec = new RSAPublicKeySpec(pStrcut.getModulus(), pStruct.getPublicExponent()); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    return kf.generatePublic(spec); 
} 
+0

¿cómo o dónde debe especificarse la estructura SubjectPublicKeyInfo? – MSSV

+0

La estructura SubjectPublicKeyInfo se especifica en el RFC 5280 (http://tools.ietf.org/html/rfc5280) y las estructuras de clave pública se especifican en el RFC 3279 (http://tools.ietf.org/html/rfc3279) – Jcs

+0

Se recibe la clave del Cliente, por lo que no podrá cambiar el formato. ¿Puede sugerir otra forma de cargar esta clave y obtener detalles del ejemplo de JCE? – MSSV

5

PEMReader de BouncyCastle lo hará por usted:

String pemKey = "-----BEGIN RSA PUBLIC KEY-----\n" 
      + "MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY\n" 
      + "mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma\n" 
      + "XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED\n" 
      + "-----END RSA PUBLIC KEY-----\n"; 
PEMReader pemReader = new PEMReader(new StringReader(pemKey)); 
RSAPublicKey rsaPubKey = (RSAPublicKey) pemReader.readObject(); 
System.out.println("Public key: "+rsaPubKey); 

(Nota . que puede necesitar en algún lugar antes Security.addProvider(new BouncyCastleProvider());)

0

usted puede construir un objeto PublicKey de la cadena que disponía lo siguiente:

  1. PEM decodificar la cadena a DER binario (usando PemReader del Castillo Hinchable)
  2. alimentación que DER binario en un analizador ASN.1 (trabaja ASN1InputStream del castillo de hinchables)
  3. Obtener los datos ASN.1 analizados por el analizador (como se ASN1Primitive de Castillo hinchable)
  4. Interpretar que los datos ASN.1 como una clave RSA (usando RSAPublicKey de Castillo hinchable)
  5. construir una especificación para la fábrica de clave de JSSE incluyendo el módulo y exponente de la clave RSA (usando RSAPublicKeySpec de Castillo hinchable)
  6. Utilice la fábrica de claves de JSSE para crear una clave pública obje ct (objeto JSSE PublicKey que necesita)

Esperaba una versión más simple, pero no pude encontrar una. Tampoco pude obtener las otras soluciones aquí para trabajar.

Pre-reqs para mi solución:

  1. Java 7+ (o tendrá que desenrollar manualmente el try-con-recursos)
  2. Castillo Hinchable bcprov-jdk15on 1.53 o posterior (posiblemente podría trabajar con antes, pero yo no lo he probado)

completa de trabajo de Java 7+ ejemplo:

import org.bouncycastle.asn1.ASN1InputStream; 
import org.bouncycastle.asn1.ASN1Primitive; 
import org.bouncycastle.asn1.pkcs.RSAPublicKey; 
import org.bouncycastle.util.io.pem.PemObject; 
import org.bouncycastle.util.io.pem.PemReader; 

import java.io.IOException; 
import java.io.StringReader; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.PublicKey; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.RSAPublicKeySpec; 

public interface PemToDer 
{ 
    static void main(String[] args) throws 
      NoSuchAlgorithmException, IOException, InvalidKeySpecException 
    { 
     createRsaPublicKey(
     "-----BEGIN RSA PUBLIC KEY-----\n" + 
     "MIGHAoGBANAahj75ZIz9nXqW2H83nGcUao4wNyYZ9Z1kiNTUYQl7ob/RBmDzs5rY\n" + 
     "mUahXAg0qyS7+a55eU/csShf5ATGzAXv+DDPcz8HrSTcHMEFpuyYooX6PrIZ07Ma\n" + 
     "XtsJ2J4mhlySI5uOZVRDoaFY53MPQx5gud2quDz759IN/0gnDEEVAgED\n" + 
     "-----END RSA PUBLIC KEY-----" 
     ); 
    } 

    static PublicKey createRsaPublicKey(String keystr) throws 
      IOException, NoSuchAlgorithmException, InvalidKeySpecException 
    { 
     try (StringReader reader = new StringReader(keystr); 
       PemReader pemReader = new PemReader(reader)) 
     { 
      PemObject pem = pemReader.readPemObject(); 
      byte[] der = pem.getContent(); 
      ASN1InputStream in = new ASN1InputStream(der); 
      ASN1Primitive primitive = in.readObject(); 
      RSAPublicKey key = RSAPublicKey.getInstance(primitive); 
      RSAPublicKeySpec spec = new RSAPublicKeySpec(
        key.getModulus(), key.getPublicExponent() 
      ); 
      KeyFactory factory = KeyFactory.getInstance("RSA"); 
      return factory.generatePublic(spec); 
     } 
    } 
} 
Cuestiones relacionadas