簡體   English   中英

如何在 JAVA 中將 RSA 私鑰從 DER 轉換為 PEM?

[英]How to convert RSA private key from DER to PEM in JAVA?

我有一個 RSA private key.der 文件(里面有一堆二進制文件)。 如何將文件轉換為 Java 中的 PEM 格式?

如果我在命令行中使用 openssl,我會這樣做:

openssl rsa -inform der -in privateKey.der -outform pem -out privateKey.pem

privateKey.pem 結果如下所示:

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyljm4IGV2JmL8amyTQz9nCSdtdJV+OGiiyefJasKuNEIVAyV
BzSNEUrJYL1LrAMM0cbenWh3M0I+RoQYfwo3J88fi/aLW5dbdU8bi001UZIeJnEB
...
...
lykp1jNHSXD8PoBNVD+pbY3zGCqH1OgPWd0/+IbMBp3Qo+HMp5Ku9w==
-----END RSA PRIVATE KEY-----

我聽說人們說 PEM 只是 DER 的 Base64 編碼表示加上某些 header 和頁腳。 但是,如果我只是做cat privateKey.der | base64 cat privateKey.der | base64

我從 openssl 給我的結果中得到了不同的結果: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDKWObggZXYmYvxqbJNDP2... ... GndCj4cynkq73

盡管有頁眉和頁腳,但 PEM 字符串也不相同。 有誰知道為什么?

Java 中是否有任何庫可以將 DER 轉換為 PEM,就像 openssl 一樣? 一直在尋找,但不幸的是,我沒有找到任何有效的方法。 任何幫助將不勝感激!

PEM 格式有很多種,OpenSSL 支持十幾種 PEMDER 格式的私鑰。 openssl rsa [-outform pem]編寫的格式是算法特定的 PKCS1 附錄 A 格式,有或沒有基於 rfc1421 的加密,並標記為RSA PRIVATE KEY openssl pkeyopenssl pkcs8 -topk8編寫的格式是算法通用的 PKCS8 格式,它定義了自己的加密,並相應地標記為PRIVATE KEYENCRYPTED PRIVATE KEY - 注意在任何一種情況下都沒有 RSA; rfc7468 Java 加密,例如PrivateKey.getEncoded()使用未加密的 PKCS8,所以如果你從 Java 得到這個 DER 並將其轉換為 Z95A1446A7120E4AF5C0C8878ABB7E6,你為什么會得到不同的結果。 另請注意,PEM 是 DER 的 base64,每 64 個字符換行一次,加上 header 和頁腳; 沒有換行符,它不會總是有效。 對於這兩者,請參見PKCS#1 和 PKCS#8 format for RSA private key

如果您擁有或可以獲得 Bouncy,那么您使用 BouncyCastle 的回答是一個很好的解決方案; bcpkix 正確處理大多數 OpenSSL 格式。 如果您想在沒有 Bouncy 的情況下執行此操作,它幾乎與How to encrypt RSA private key with PBE in PKCS#5 format in Java with IAIK JCE 相同? (我的)除了沒有加密,所以省略中間塊並稍微更改 PEM header:

    // given [RSA]PrivateKey privkey, get the PKCS1 part from the PKCS8 encoding
    byte[] pk8 = privkey.getEncoded();
    // this is wrong for RSA<=512 but those are totally insecure anyway
    if( pk8[0]!=0x30 || pk8[1]!=(byte)0x82 ) throw new Exception();
    if( 4 + (pk8[2]<<8 | (pk8[3]&0xFF)) != pk8.length ) throw new Exception();
    if( pk8[4]!=2 || pk8[5]!=1 || pk8[6]!= 0 ) throw new Exception();
    if( pk8[7] != 0x30 || pk8[8]==0 || pk8[8]>127 ) throw new Exception();
    // could also check contents of the AlgId but that's more work
    int i = 4 + 3 + 2 + pk8[8];
    if( i + 4 > pk8.length || pk8[i]!=4 || pk8[i+1]!=(byte)0x82 ) throw new Exception();
    byte[] old = Arrays.copyOfRange (pk8, i+4, pk8.length);
    
    // write to PEM format (substitute other file if desired)
    System.out.println ("-----BEGIN RSA PRIVATE KEY-----");
    String b64 = Base64.getEncoder().encodeToString(old);
    for( int off = 0; off < b64.length(); off += 64 )
        System.out.println (b64.substring(off, off+64<b64.length()?off+64:b64.length()));
    System.out.println ("-----END RSA PRIVATE KEY-----");

不過,在稱其為“更好”之前,我會仔細考慮。 這也類似於Convert a X509 Public key to RSA public key for publickey (also mine) 和Read a PKCS#1 or SPKI public key in Java without libraries 的相反

經過大量挖掘......我找到了一種方法,但它看起來是多余的。 如果您有更好的主意,請告訴我。

    // My private key DER file.
    byte[] privateKeyDerBytes = Files.readAllBytes(Paths.get("tst/resource/FromSecretsManager.der"));
    
    // Convert the DER file to a Java PrivateKey
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyDerBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PrivateKey pk = factory.generatePrivate(spec);

    // Use PemWriter to write the key to PEM format
    StringWriter sw = new StringWriter();
    try (PemWriter pw = new PemWriter(sw)) {
        PemObjectGenerator gen = new JcaMiscPEMGenerator(pk);
        pw.writeObject(gen);
    }
    String privateKeyPem = sw.toString();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM