2011-12-05 9 views
0

Javaのkeytoolには、秘密鍵から新しい鍵ストアを作成する機能や、既存のjksストアに秘密鍵をインポートする機能はありません。私は彼らが秘密鍵を生成し、私たちにクライアント、彼らのサービスを呼び出すことを要求するサービスホストを持っています。JavaおよびHTTPSでインポートされた秘密鍵の問題

秘密鍵と証明書がfirefoxでダウンロードされ、Windowsマシン上でp12形式のファイルにエクスポートされます。私はopensslを使ってそのpkcs12をPEMファイルに変換しました。私は手動でそのファイルをそれぞれcert.derファイルとprivateKey.derファイルに分割しました。私はその後、このペアを既存のキーストアにインポートするJavaプログラムを作成しました(弾力のある城を使用します)。キーストアが作成されていることを確認し、プログラムを実行した後にキー/証明書がkeytoolに含まれていることを確認します。

実行時のプログラムコードとエラーメッセージは次のとおりです。私はkeytool -printcertがView Certificateメニューのfirefoxと違っているときの指紋署名に気付きました、それは赤い旗ですか?

ここで見ていることや思考についての助けを非常に感謝します。

private static InputStream fullStream(String fname) throws IOException { 
     File f = new File(fname); 
     if (f == null || f.exists() == false) { 
      System.out.println("File " + fname + " does not exist"); 
      System.exit(1); 
     } 
     FileInputStream fis = new FileInputStream(f); 
     DataInputStream dis = new DataInputStream(fis); 
     byte[] bytes = new byte[dis.available()]; 
     dis.readFully(bytes); 
     ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 
     return bais; 
    } 


    public static void main(String args[]) { 
     try { 
      if (args.length < 6) { 
       System.out 
         .println("\nImportPrivateKeyTool Usage: \njava ImportPrivateKeyTool parameters:\n" 
           + "\n<keystoreFileName> - JKS format\n" 
           + "\n<keystorePassword>\n" 
           + "\n<keyFileName> - PKCS12 format \n" 
           + "\n<keyPwd>\n" 
           + "\n<keyAlias>\n"); 
       System.out 
         .println("\n\nRequires jsse for PKCS12 keystore support \n" 
           + " - source storetype can be JKS or PKCS12\n" 
           + " - destination storetype must be JKS type (PKCS12 write not supported)\n"); 
       System.exit(1); 
      } 

      String keystoreFileName = args[0]; 
      String keystorePassword = args[1]; 
      String keyFileName = args[2]; 
      String keyPwd = args[3]; 
      String keyAlias = args[4]; 
      String certFileName = args[5]; 

      System.setProperty("javax.net.ssl.keyStore", keystoreFileName);// ie 
                      // "C:/Dev/security/keystores/.deluxeKeyStore.jks" 
      System.setProperty("javax.net.ssl.keyStorePassword", 
        keystorePassword); 

      Security.addProvider(new BouncyCastleProvider()); 

      // initializing keystore , clear it first by passing null?? 
      KeyStore ks = KeyStore.getInstance("JKS");// second param SUN? 
                 // "SUN", //TODO allow 
                 // passing of PKCS12 or 
                 // JKS? 

      File f = new File(keystoreFileName); 
      if (f == null || f.exists() == false) { 
       //create new 
       ks.load(null, keystorePassword.toCharArray());//initialize 
       ks.store(new FileOutputStream(keystoreFileName),keystorePassword.toCharArray()); 
       System.out.println("Keystore file " + keystoreFileName + " did not exist so created new key store."); 
      } 

      ks.load(fullStream(keystoreFileName),keystorePassword.toCharArray()); 
      System.out.println("Using keystore-file : " + keystoreFileName); 



      KeyFactory kf = KeyFactory.getInstance("RSA"); 

      BufferedReader br = new BufferedReader(new FileReader(keyFileName)); 
      PEMReader privateKeyPEMReader = new PEMReader(br); 
      KeyPair kp = (KeyPair) privateKeyPEMReader.readObject(); 
      PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded()); 
      PrivateKey ff = kf.generatePrivate(keysp);//keysp 
      System.out.println("Successfully loaded into memory private key: "+ keyFileName); 

      // loading CertificateChain 
      CertificateFactory cf = CertificateFactory.getInstance("X.509");of 
      BufferedReader br2 = new BufferedReader(new FileReader(certFileName));// cert? 
      //InputStream certstream = fullStream(certFileName); 
      PEMReader certPEMReader = new PEMReader(br2); 
      Certificate cert = (Certificate)certPEMReader.readObject(); //TODO support chain array of certs.. 
      Certificate[] certs = new Certificate[1]; 
      certs[0] = cert; 


      // storing keystore 
      ks.setKeyEntry(keyAlias, ff, keyPwd.toCharArray(), certs); 
      System.out 
        .println("Key and certificate successfully imported as alias:" 
          + keyAlias); 
      ks.store(new FileOutputStream(keystoreFileName), 
        keystorePassword.toCharArray()); // TODO use key pass 
                 // instead? doubt it 
      System.out.println("Successfully saved updated key store."); 







ClientKeyExchange, RSA PreMasterSecret, TLSv1 
main, WRITE: TLSv1 Handshake, length = 876 
SESSION KEYGEN: 
PreMaster Secret: 
<removed>.... 
CONNECTION KEYGEN: 
Client Nonce: 
<remove>..... 
Server Nonce: 
<remove> 
Master Secret: 
<removed> 
Client MAC write Secret: 
<removed> 
Server MAC write Secret: 
<removed> 
Client write key: 
<removed> 
Server write key: 
<removed> 
... no IV used for this cipher 
*** CertificateVerify 
main, WRITE: TLSv1 Handshake, length = 262 
main, WRITE: TLSv1 Change Cipher Spec, length = 1 
*** Finished 
verify_data: { 20, 221, 183, 152, 78, 193, 208, 28, 198, 116, 172, 58 } 
*** 
main, WRITE: TLSv1 Handshake, length = 32 
main, READ: TLSv1 Alert, length = 2 
main, RECV TLSv1 ALERT: fatal, decrypt_error 
main, called closeSocket() 
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: decrypt_error 
javax.net.ssl.SSLHandshakeException: Received fatal alert: decrypt_error 
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234) 
    at com.oflows.seam.test.deluxechecks.DeluxeChecksOrderProTest.main(DeluxeChecksOrderProTest.java:84) 
+0

あなたは 'CertificateFactory'を使用していないようです。 'kp.getPrivate()'から直接取得できるときに、なぜ新しい 'PrivateKey'インスタンス(' ff')を再生成するのか、私は確信していません。 'OutputStream'を正しく閉じることもお勧めします。特に、同じファイル名を使って2つの異なるファイルに書き込んでいるようです。 – Bruno

答えて

0

私は、エンド目標が何であるかを理解していない...

  • あなたがPKCS#12ファイルに既にある証明書+秘密鍵を使用したい場合は、それを変換する必要はありません:JavaでPKCS12キーストアタイプを使用してください。使用しているクライアントコードは表示されませんが、使用する方法の1つはjavax.net.ssl.keyStoreTypePKCS12に設定することです。

  • keytool

    、Java 6のためのSun/Oracleが提供されるように、例えば、別のものに(PKCS#12を含む)キーストアから証明書+秘密鍵のペアをインポートすることができ:

    keytool -importkeystore -srckeystore thekeystore.p12 \ 
           -srcstoretype PKCS12 \ 
           -destkeystore thekeystore.jks \ 
           -deststoretype JKS 
    

これらのオプションにはBouncyCastleは必要ありません(OpenSSL経由でのエクスポートも必要ありません)。

関連する問題