2017-05-09 39 views
1

RSA CA KeyPairと証明書を生成し、キーストアに保存しようとしました。 私のコードは次のとおりです。JavaキーストアからキーストアへKeyStoreException

import java.io.FileOutputStream; 
import java.math.BigInteger; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.KeyStore; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.security.cert.X509Certificate; 
import java.util.Date; 

import org.bouncycastle.asn1.x500.X500Name; 
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 
import org.bouncycastle.cert.X509CertificateHolder; 
import org.bouncycastle.cert.X509v3CertificateBuilder; 
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.operator.ContentSigner; 
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 

    private static final String storeType = "PKCS12"; 
     private static final String storePassword = "password"; 
     private static final String storePath = "/usr/lib/java/keystore.ks"; 
     private static final Date startDate = new Date(System.currentTimeMillis());           // time from which certificate is valid 
     private static final Date expiryDate = new Date(System.currentTimeMillis() + 2L * 365L * 24L * 60L * 60L * 1000L); // time after which certificate is not valid (2 years) 
     private static final BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); 
     private static X500Name issuer; 
     private static X500Name subject; 
     private static KeyPair pair; 

     public static void saveKeys() throws Exception{ 
      Security.addProvider(new BouncyCastleProvider()); 

      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 
      keyPairGen.initialize(2048, new SecureRandom()); 
      pair = keyPairGen.generateKeyPair(); 
      byte[] pub = pair.getPublic().getEncoded(); 
      byte[] priv = pair.getPrivate().getEncoded(); 
      SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(pub); 

      issuer = new X500Name("CN=CA"); 
      subject = issuer; 

      X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
        issuer,  //issuer (CA) 
        serialNumber, 
        startDate, expiryDate, 
        subject,  //subject 
        pubInfo); 

      //signature for sig 
      ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSA").build(pair.getPrivate()); 
      X509CertificateHolder certHolder = certBuilder.build(sigGen); 
      X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(certHolder); 

      X509Certificate[] chain = new X509Certificate[3]; 
      chain[2] = caCert; 

      KeyStore store; 
      try { 
       store = KeyStore.getInstance(storeType); 
       store.load(null,null); 
      store.setKeyEntry("CA-Key", priv, chain); 
      store.store(new FileOutputStream("public.p12"), null); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

その後、私はエラーを取得:

java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: overrun, bytes = 1194 
    at sun.security.pkcs12.PKCS12KeyStore.engineSetKeyEntry(PKCS12KeyStore.java:687) 
    at java.security.KeyStore.setKeyEntry(KeyStore.java:1174) 
    at storeKeys.saveKeys(storeKeys.java:95) 
    at storeKeys.main(storeKeys.java:146) 
Caused by: java.io.IOException: overrun, bytes = 1194 

にはどうすれば適切なフォーマットへの秘密鍵を暗号化することができますか?キーストアにキーを保存するためのパスをどこに与えることができますか?

答えて

2

あなたがそのメソッドのJavaのドキュメントを参照している場合、それは言う:

Assigns the given key (that has already been protected) to the given alias.

If the protected key is of type java.security.PrivateKey, it must be accompanied by a certificate chain certifying the corresponding public key. If the underlying keystore implementation is of type jks, key must be encoded as an EncryptedPrivateKeyInfo as defined in the PKCS #8 standard.

これは、JKS氏は述べていますが、それはまたPKCS12のための暗号化された秘密キーの形式を期待しているように見えます。

したがって、秘密鍵のバイト配列を渡すことはできません。

物事を容易にするために、あなたがこれを行うことができます:

PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(pair.getPrivate(), chain); 
store.setEntry("CA-Key", privateKeyEntry, new KeyStore.PasswordProtection(storePassword.toCharArray())); 

そして、あなたのkeystore.store(..)方法では、最初の引数は、キーストアのパスです。 2番目の引数はキーストアのパスワードです。

だから、このような何かを行うことができます:

store.store(new FileOutputStream(new File(storePath)), storePassword.toCharArray()); 
+0

は私にjava.security.KeyStoreクラス$てPrivateKeyEntryのスレッドでの例外 "メイン" java.lang.NullPointerExceptionが \tを与えます。 (KeyStore.java:532) \t(java.security.KeyStore $ PrivateKeyEntry)。 (KeyStore.java:491) – nolags

+1

証明書チェーンが原因である可能性があります。 'chain'変数に格納している自己署名証明書は1つしかありません。しかし、あなたが定義したサイズは3で、配列の3番目の位置に自己署名証明書を格納します。したがって、最初の2つはnullです。サイズを1に変更し、自己署名証明書を0番目の場所に置き、再度ショットを付けてください。 –

+0

ああ愚かな間違い。それはありがとうございます。 – nolags

関連する問題