2013-08-21 35 views
6

Javaの文字列(.pemファイル)から秘密鍵を生成したいとします。Javaの* pem文字列からRSA秘密鍵を生成する方法

private static final String test = "-----BEGIN RSA PRIVATE KEY-----\n" + 
     "MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" + 
// and so on 
     "-----END RSA PRIVATE KEY-----"; 

try { 
    String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", ""); 
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", ""); 

    byte [] encoded = Base64.decode(privKeyPEM); 

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    PrivateKey privKey = kf.generatePrivate(keySpec); 
} 
catch (Exception e) { 
    e.printStackTrace(); 
} 

最後の行(generatePrivate機能)は、この例外がスローされます。

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence 
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source) 
    at java.security.KeyFactory.generatePrivate(Unknown Source) 
    at Test.main(Test.java:52) 
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence 
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source) 
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source) 
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source) 
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source) 
    at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source) 
    ... 3 more 

私はそれが正常に動作する.derファイルから値への秘密鍵を変更するが、私はプライベートを生成する必要がある場合キーファイルを.pemファイルから削除します。

文字列として印刷されたバイトのスクリーンショットを貼り付けました(\ nで一度ハードコードされ、\ nなしで一度ハードコードされた後)。

Bigger Image

Output

奇妙なことは、ファイルからの出力が文字列からの出力に異なることです。

.derファイルをBase64でエンコードしようとすると、結果は.pemファイルの文字列と異なります。どうしてこんなことに?あなたが最後の行は、例外をスローしていると言う

+0

答えが見つかりましたか? –

+0

@SankarPは実際にはそうではありません。 – Niklas

+0

大丈夫です。私は解決策を見つけました。 "----- BEGIN RSA PRIVATE KEY"で始まるキーは、pkcs1でエンコードされたファイルです。このpkcs1エンコーディングは、BouncyCastleのような外部ライブラリ以外のJavaではサポートされていません。私は昨日同じ問題に遭遇し、約8時間後に解決策を見つけました。 pkcs8で秘密鍵をエンコードすると、株式Javaによって処理される "--- BEGIN PRIVATE KEY ---"のように始まります。 HTH。 –

答えて

1

、線の上すなわち

PrivateKey privKey = kf.generatePrivate(keySpec);

すなわち

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

だから、実際の問題は、符号化されたバイトであり、正しい設定されているkeyspecs上で動作しますアレイ。 byte [] encoded = Base64.decode(privKeyPEM);の後にSystem.outを実行し、出力が何であるかを確認してください。

メッセージがMIME形式である場合、特定の文字の後に、キャリッジリターンと改行の組み合わせが追加されるため、電子メールシステムや使用している場所の文字列が長すぎることはありません。

最終的な文字列テストには、元のテキストに「\ n」という文字列が含まれています。あなたは、下の行に他のテキストを取り除くでし

String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", ""); 
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", ""); 

しかし、文字列を見て、

"MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" + 
// and so on 
     "-----END RSA PRIVATE KEY-----"; 

それはいくつかのより多くを有することができる「\ n」のとき、いくつかの不要な文字をもたらし得る左keyspecを生成します。より多くのSystem.outを試して、エンコードされたバイト配列がどのようなものであるかを確認してから、その文字列privKeyPEMをチェックして余分な文字が残っていないかどうか確認してください。

このheplsを希望します。

+1

'encoded 'の出力をアップロードしました。 http://pastebin.com/YUsNdhgW。私は '\ n'を使わずにテストを純粋な文字列に変更し、それもうまくいきませんでした。 – Niklas

+0

また、出力を文字列としてスクリーンショットをアップロードしました。 – Niklas

+0

Base64デコードでは、改行や通常はすべての空白が無視されます。 –