2010-10-27 42 views
10

có một chuỗi được gửi từ trong định dạng dưới đây:Làm thế nào để chúng ta chuyển đổi một chuỗi từ PEM để der định dạng

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

Làm thế nào để tôi xây dựng một Object PublicKey từ chuỗi này? đã thử dưới đây Tháo header và footer và base64 giải mã bộ đệm

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

    } 

Đây không bất kể là định dạng chính không hợp lệ hoặc sẽ nhận được dưới đây lỗi

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) 

The Key đang được tạo xuyên qua các API của openSSL PEM_write_bio_RSAPublicKey(bio, rsa);

+0

đã sử dụng liên kết .Nhưng sẽ không làm converstion để der định dạng – MSSV

+0

Lưu ý rằng những gì bạn đang cố gắng làm không thực sự là "chuyển đổi thành DER". Chuyển đổi thành DER chỉ giải mã base64 ở đây và xuất nó như là một chuỗi các byte. Bạn đang cố gắng giải mã cấu trúc ASN.1. – Bruno

Trả lời

9

bằng cách gọi PEM_write_bio_RSAPublicKey chỉ mô-đun chính và số mũ công khai được mã hóa vào dữ liệu PEM đầu ra. Tuy nhiên, X509EncodedKeySpec dự kiến ​​ASN.1 này định dạng chính:

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

Bạn nên sử dụng chức năng PEM_write_bio_PUBKEY mã hóa khóa công khai sử dụng cấu trúc SubjectPublicKeyInfo mà như mong đợi bởi X509EncodedKeySpec

Một giải pháp khác có thể giải mã Chìa khóa. Đáng tiếc là tôi không nghĩ rằng nó có thể làm chỉ với JDK API chuẩn nhưng nó có thể được thực hiện với sự Bouncycastle thư viện

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ấu trúc SubjectPublicKeyInfo nên được chỉ định như thế nào hoặc ở đâu? – MSSV

+0

Cấu trúc SubjectPublicKeyInfo được chỉ định trong RFC 5280 (http://tools.ietf.org/html/rfc5280) và các cấu trúc khóa công khai được chỉ định trong RFC 3279 (http://tools.ietf.org/html/rfc3279) – Jcs

+0

Khóa khách hàng được nhận vì vậy sẽ không thể thay đổi định dạng. Bạn có thể đề xuất bất kỳ cách nào khác để tải khóa này và nhận ví dụ về chi tiết JCE. – MSSV

5

PEMReader BouncyCastle sẽ làm việc này cho bạn:

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

(Lưu ý . mà bạn có thể cần Security.addProvider(new BouncyCastleProvider()); ở đâu đó trước đó)

0

bạn có thể xây dựng một Object PublicKey từ chuỗi mà bạn cung cấp như sau:

  1. PEM giải mã chuỗi để DER nhị phân (sử dụng PemReader Bouncy Castle)
  2. ăn mà nhị phân DER thành một phân tích cú pháp ASN.1 (ASN1InputStream Castle của Bouncy của hoạt động)
  3. Get dữ liệu ASN.1 phân tích cú pháp từ phân tích cú pháp (như ASN1Primitive Bouncy Castle)
  4. Giải thích rằng dữ liệu ASN.1 như một chìa khóa RSA (sử dụng RSAPublicKey Bouncy Castle)
  5. Xây dựng một đặc điểm kỹ thuật cho nhà máy chính JSSE của bao gồm các mô đun và số mũ của khóa RSA (sử dụng RSAPublicKeySpec Bouncy Castle)
  6. Sử dụng nhà máy chính của JSSE để tạo ra khóa công khai ct (đối tượng JSSE PublicKey bạn cần)

Tôi đã hy vọng đơn giản hơn nhưng không thể tìm thấy. Tôi cũng không thể có được các giải pháp khác ở đây để làm việc.

Pre-reqs cho giải pháp của tôi:

  1. Java 7+ (hoặc bạn sẽ cần phải tự cuộn try-với-nguồn lực)
  2. Bouncy Castle bcprov-jdk15on 1.53 hoặc mới hơn (cho là có thể làm việc với trước đó, nhưng tôi đã không kiểm tra nó)

Full làm việc Java 7+ dụ:

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); 
     } 
    } 
} 
Các vấn đề liên quan