2010-10-27 11 views
10

avere una stringa di essere inviato dal nel formato di seguito:Come si fa a convertire una stringa da PEM Der formato

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

Come faccio a costruire un oggetto PublicKey da questa stringa? hanno provato il sotto Rimuovere l'intestazione e piè di pagina e base64 decodificare il 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); 

    } 

Questo fallisce sia come formato di chiave valida o otterrà sotto l'errore

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) 

il tasto viene generato thro il API di openSSL PEM_write_bio_RSAPublicKey(bio, rsa);

+0

hanno usato il link .Ma non farà il converstion a der format – MSSV

+0

Nota che quello che stai cercando di fare non è realmente una "conversione in DER". La conversione in DER è solo la decodifica di ciò che è base64 qui e l'output come una sequenza di byte. Stai cercando di decodificare la struttura ASN.1. – Bruno

risposta

9

chiamando PEM_write_bio_RSAPublicKey solo il modulo chiave e l'esponente pubblico sono codificati nei dati PEM di uscita. Tuttavia il X509EncodedKeySpec si aspetta questo ASN.1 formato chiave:

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

si dovrebbe utilizzare la funzione PEM_write_bio_PUBKEY che codifica la chiave pubblica utilizzando la struttura SubjectPublicKeyInfo che, come previsto dal X509EncodedKeySpec

Un'altra soluzione possibile per decodificare il chiave. Purtroppo non credo sia possibile fare solo con l'API standard JDK, ma può essere fatto con la Bouncycastle libreria

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

come o dove deve essere specificata la struttura SubjectPublicKeyInfo? – MSSV

+0

La struttura SubjectPublicKeyInfo è specificata nella RFC 5280 (http://tools.ietf.org/html/rfc5280) e le strutture delle chiavi pubbliche sono specificate nella RFC 3279 (http://tools.ietf.org/html/rfc3279) – Jcs

+0

La chiave del client viene ricevuta quindi non sarà possibile modificare il formato. Puoi suggerire un altro modo per caricare questa chiave e ottenere i dettagli dall'esempio JCE. – MSSV

5

PEMReader di BouncyCastle farà questo per voi:

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 . che potrebbe essere necessario Security.addProvider(new BouncyCastleProvider()); da qualche parte prima)

0

è possibile costruire un oggetto PublicKey dalla stringa che hai fornito i seguenti:

  1. PEM decodifica la stringa da DER binario (usando PemReader di Bouncy Castle)
  2. alimentazione che DER binario in un parser ASN.1 (ASN1InputStream di di Bouncy Castle funziona)
  3. ottenere i dati ASN.1 analizzati dal parser (come ASN1Primitive di Bouncy Castle)
  4. interpretare tale dati ASN.1 come una chiave RSA (usando RSAPublicKey di Bouncy Castle)
  5. costruire una specifica per la fabbrica chiave di JSSE tra cui il modulo e esponente della chiave RSA (usando RSAPublicKeySpec di Bouncy Castle)
  6. Utilizzare la fabbrica di chiavi JSSE per creare un oggetto chiave pubblico ct (JSSE PublicKey oggetto necessario)

Speravo in un modo più semplice, ma non riuscivo a trovarne uno. Anche io non sono riuscito a far funzionare le altre soluzioni qui.

Pre-reqs per la mia soluzione:

  1. Java 7+ (o è necessario srotolare manualmente il try-with-risorse)
  2. Bouncy Castle bcprov-jdk15on 1.53 o versione successiva (potrebbe forse lavorare con i precedenti, ma non ho provato)

completa Java lavoro 7+ esempio:

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); 
     } 
    } 
} 
Problemi correlati