2010-10-27 18 views
10

Czy String wysyłanych z poniższa formacie:Jak przekonwertować ciąg z PEM Der formatu

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

Jak skonstruować obiektu PublicKey z tego ciągu? próbowałem poniżej Usunąć nagłówek i stopkę i base64 zdekodować bufora

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); 

    } 

ta zawodzi albo jako nieprawidłowym formacie klucza lub dostanie poniżej błędu

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) 

Klucz jest generowany thro API of openSSL PEM_write_bio_RSAPublicKey(bio, rsa);

+0

wykorzystali link .Ale nie zrobi converstion Der format – MSSV

+0

Należy zauważyć, że to, co próbujesz zrobić, nie jest tak naprawdę "konwersją do DER". Konwersja na DER polega właśnie na dekodowaniu tego, co jest tutaj base64 i wyprowadzeniu go jako sekwencji bajtów. Próbujesz zdekodować strukturę ASN.1. – Bruno

Odpowiedz

9

przez wywołanie PEM_write_bio_RSAPublicKey tylko moduł klucza i wykładnik publiczny są zakodowane w wyjściowych danych PEM. Jednak oczekuje się tego formatu ASN.1 kluczową X509EncodedKeySpec:

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

należy użyć funkcji PEM_write_bio_PUBKEY który koduje klucz publiczny przy użyciu struktury subjectPublicKeyInfo który zgodnie z oczekiwaniami X509EncodedKeySpec

Innym możliwym rozwiązaniem do dekodowania klawisz. Niestety nie sądzę, że jest to możliwe do zrobienia tylko ze standardowym JDK API, ale można to zrobić z biblioteką Bouncycastle

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

Jak lub gdzie powinna być określona struktura SubjectPublicKeyInfo? – MSSV

+0

Struktura SubjectPublicKeyInfo jest określona w specyfikacji RFC 5280 (http://tools.ietf.org/html/rfc5280), a struktury kluczy publicznych są określone w specyfikacji RFC 3279 (http://tools.ietf.org/html/rfc3279) – Jcs

+0

Otrzymano klucz klienta, więc nie będzie możliwości zmiany formatu. Możesz zaproponować inny sposób załadowania tego klucza i uzyskania szczegółowych informacji na przykład JCE. – MSSV

5

BouncyCastle za PEMReader zrobi to za ciebie:

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); 

(Note ., że może trzeba Security.addProvider(new BouncyCastleProvider()); gdzieś wcześniej)

0

można skonstruować obiekt publicKey z łańcucha podany następująco:

  1. PEM dekodowania ciąg Der binarnym (przy użyciu nadmuchiwany zamek za PemReader)
  2. Karmienie że binarny DER do parsera ASN.1 (nadmuchiwany za Castle'a ASN1InputStream działa)
  3. Get przeanalizowane dane ASN.1 z parsera (jak nadmuchiwany zamek za ASN1Primitive)
  4. zinterpretować dane ASN.1 jak klucz RSA (z użyciem RSAPublicKey dmuchanym zamku)
  5. skonstruować specyfikację dla kluczowego fabryce JSSE w tym moduł i wykładnik klucza RSA (przy dmuchanym zamku RSAPublicKeySpec)
  6. Użyj kluczowej fabryki JSSE, aby utworzyć klucz publiczny ct (obiekt JSSE PublicKey, którego potrzebujesz)

Miałem nadzieję na prostsze, ale nie mogłem go znaleźć. Nie mogłem też znaleźć tutaj innych rozwiązań.

Pre-reqs dla mojego rozwiązania:

  1. Java 7+ (lub musisz ręcznie rozwinąć try-with-zasobów)
  2. nadmuchiwany zamek bcprov-jdk15on 1.53 lub później (prawdopodobnie mógłby pracować wcześniej, ale ja jej nie testowane)
przykład

Full Java pracujących 7+:

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); 
     } 
    } 
} 
Powiązane problemy