2013-09-05 4 views
6

を使用しては正しく、次のように私の問題があるbouny城に

を中間証明書を使用して新しい証明書を作成する基本的に私は弾むの城(jdk16バージョン1.46)を使用して、証明書チェーンを作成したいです。私はむしろバウンシーキャッスルとjava.securityの新機能ですので、私のアプローチが完全に間違っているかもしれませんが、とにかくこれは私がしたことです:

これまでのところ私はルート証明書。これは、次のコードを使用して行われます:

//-----create CA certificate with key 
KeyPair caPair = Signing.generateKeyPair("DSA", 1024, null, null); 

は、これは基本的に鍵ペアを作成し、必要に応じて、2つのヌルのオプションは、プロバイダとの安全なランダムのためのものです。

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> caMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>(); 
caMap.put(X509Extensions.BasicConstraints, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(true, new BasicConstraints(true))); 

//------this creates the self signed certificate   
X509Certificate caCert = X509CertificateGenerator.generateX509Certificate(serial, "CN=CA", "CN=CA", start, end, "SHA1withDSA", caPair.getPrivate(), caPair.getPublic(), null, caMap); 

これにより、指定された属性を持つ証明書が作成されます。

  • シリアル=単にミリ秒単位の現在時刻が
  • 開始=シリアルと同様、基本的に開始=
  • 端(1又は2ミリ秒の差を有していてもよい)+ 2日
  • 単に

地図証明書をCAに設定するための基本的な制約が追加されています。必要に応じて追加のX509Extensionsを追加できるようにしたいので、ここでマップを使用します。

//-----save ca certificate in PEM format 
X509CertificateGenerator.savePemX509Certificate(caCert, caPair.getPrivate(), caWriter); 

これは、bouncy caste pem writerを使用して証明書と秘密鍵をpemファイルに格納します。

その後、ファイルが生成され、ファイルをインストールすることもできます(IEを使用し、インターネットオプションを介して信頼できるCAとしてインストールします)。証明書も有効です。

その後、私は、次のコードを使用して、中間証明書を作成する(上記のコードに注意し、これらの変数は同様に利用可能であるように、同じ範囲内にある)

KeyPair intermediatePair = Signing.generateKeyPair("DSA", 1024, null, null);  

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> intermediateMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>(); 
intermediateMap.put(X509Extensions.AuthorityKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new AuthorityKeyIdentifierStructure(caCert))); 
intermediateMap.put(X509Extensions.SubjectKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new SubjectKeyIdentifierStructure(intermediatePair.getPublic()))); 

X509Certificate intermediateCert = X509CertificateGenerator.generateX509Certificate(serial.add(BigInteger.valueOf(1l)), "CN=intermediate", caCert.getSubjectX500Principal().toString(), start, end, "SHA1withDSA", caPair.getPrivate(), intermediatePair.getPublic(), null, intermediateMap); 

//-----save intermediate certificate in PEM format 
X509CertificateGenerator.savePemX509Certificate(intermediateCert, intermediatePair.getPrivate(), intermediateWriter); 

手順はIしかし、bascially同じです追加X509Extensionsを追加します。

  • X509Extensions.AuthorityKeyIdentifier =は=はPUBLを発生、使用し、中間体の親
  • X509Extensions.SubjectKeyIdentifierとしてCA証明書を設定し、証明書のic鍵

さらに、CAを発行者として使用し、CA秘密鍵を使用して中間証明書を作成します。

これも機能し、中間証明書(IEを再度使用して)をインストールできます。また、親certififcateが生成されたCA証明書であり、証明書が有効であることも示されます。

私は間違いを犯しているところですが、ここではトリッキーな部分があります。次のコードを使用して、中間証明書を使用して新しい証明書を作成します。

KeyPair endPair = Signing.generateKeyPair("DSA", 1024, null, null); 

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> endMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>(); 
endMap.put(X509Extensions.AuthorityKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new AuthorityKeyIdentifierStructure(intermediateCert))); 
endMap.put(X509Extensions.SubjectKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new SubjectKeyIdentifierStructure(endPair.getPublic()))); 

X509Certificate endCert = X509CertificateGenerator.generateX509Certificate(serial.add(BigInteger.valueOf(1l)), "CN=end", intermediateCert.getSubjectX500Principal().toString(), start, end, "SHA1withDSA", intermediatePair.getPrivate(), endPair.getPublic(), null, endMap); 

X509CertificateGenerator.savePemX509Certificate(endCert, endPair.getPrivate(), endWriter); 

基本的には、中間証明書の作成と同じです。しかし、私は今、次のX509Extensionの設定を使用します。

  • はX509Extensions.AuthorityKeyIdentifier =証明書の親として中間証明書を設定します
  • X509Extensions.SubjectKeyIdentifier =証明書も

のための公開鍵を生成し、使用しています中間証明書が発行者として使用され、その秘密鍵が証明書の作成に使用されます。

私は新しい証明書をインストールすることもできますが、(IEも)検証すると、「このCAは証明書を発行する資格がないか、証明書を使用できません-エンティティ。"

私は何とか新しい証明書を作成できるように、何らかの理由でKeyUsages/ExtendedKeyUsageを追加することで、中間証明書を有効にする必要があります。

誰かが中間証明書をどのようにして必要とするのかを知っている人がいるのですか?

EDIT 1:私は、証明書およびPEM形式でそれを保存したものを作成したメソッドのコードを提供するのを忘れ

だから、大丈夫(古いものはmisguidingたので、私はsavePemX509Certificateにそれを改称) 。

証明書の生成のためのコード:証明書のsaveingため

public static X509Certificate generateX509Certificate(BigInteger serialnumber, String subject, String issuer, Date start , Date end, String signAlgorithm, PrivateKey privateKey, PublicKey publicKey, String provider, Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> map) throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException 
{ 
    if(serialnumber!=null && subject!=null && issuer!=null && start!=null && end!=null && signAlgorithm !=null && privateKey!=null && publicKey!=null) 
    { 
     //-----GENERATE THE X509 CERTIFICATE 
     X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); 
     X509Principal dnSubject = new X509Principal(subject); 
     X509Principal dnIssuer = new X509Principal(issuer); 

     certGen.setSerialNumber(serialnumber); 
     certGen.setSubjectDN(dnSubject); 
     certGen.setIssuerDN(dnIssuer); 
     certGen.setNotBefore(start); 
     certGen.setNotAfter(end); 
     certGen.setPublicKey(publicKey); 
     certGen.setSignatureAlgorithm(signAlgorithm); 

     //-----insert extension if needed 
     if(map!=null) 
      for(ASN1ObjectIdentifier extension : map.keySet()) 
       certGen.addExtension(extension, map.get(extension).getKey(), map.get(extension).getValue()); 

     return certGen.generate(privateKey, provider); 
    } 
    return null; 
} 

コードとキー:

public static boolean savePemX509Certificate(X509Certificate cert, PrivateKey key, Writer writer) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateEncodingException, SignatureException, InvalidKeyException, IOException 
{  
    if(cert!=null && key!=null && writer!=null) 
    {    
     PEMWriter pemWriter = new PEMWriter(writer); 
     pemWriter.writeObject(cert); 
     pemWriter.flush(); 

     if(key!=null) 
     { 
      pemWriter.writeObject(key); 
      pemWriter.flush(); 
     } 
     pemWriter.close(); 
     return true; 
     } 
    return false; 
} 

あなたは、私は基本的にファイルに証明書と鍵を置く見ることができるように、それで全部です。結果は次のようなもので、私にとっては良いようです。秘密鍵は、その公開鍵と同じ鍵ペアからのものである場合gtrigが証明書を作成するための正しい方法を私に提供した後、だから、私は正常または自己のいずれかを作成するには、このメソッドを使用して終了

-----BEGIN CERTIFICATE----- 
MIICdjCCAjagAwIBAgIGAUDuXLRLMAkGByqGSM44BAMwDTELMAkGA1UEAwwCQ0Ew 
HhcNMTMwOTA1MTM0MzA3WhcNMTMwOTA3MTM0MzA3WjANMQswCQYDVQQDDAJDQTCC 
AbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADD 
Hj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gE 
exAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/Ii 
Axmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4 
V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozI 
puE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4Vrl 
nwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgAeFoGATLbIr8+QNuxcbYJ7RhbefKWSC 
Br67Pp4Ynikxx8FZN4kCjGX7pwT1KffN3gta7jxIXNM5G3IFbs4XnYljh5TbdnjP 
9Ge3kxpwncsbMQfCqIwHh8T5gh55KaxH7yYV2mrtEEqj7NBL4thQhJe2WGwgkB9U 
NxNmLoMq3m4poyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAJ 
BgcqhkjOOAQDAy8AMCwCFFm5ybLY09y8y2uGsEnpceffy2KaAhQIyshgy3ohCLxQ 
q3CmnvC+cfT2VQ== 
-----END CERTIFICATE----- 
-----BEGIN DSA PRIVATE KEY----- 
MIIBuwIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR 
+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb 
+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg 
UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX 
TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj 
rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB 
TDv+z0kqAoGAB4WgYBMtsivz5A27FxtgntGFt58pZIIGvrs+nhieKTHHwVk3iQKM 
ZfunBPUp983eC1ruPEhc0zkbcgVuzhediWOHlNt2eM/0Z7eTGnCdyxsxB8KojAeH 
xPmCHnkprEfvJhXaau0QSqPs0Evi2FCEl7ZYbCCQH1Q3E2YugyrebikCFDJCJHtt 
NWB4LWYc4y4QvJ/l46ap 
-----END DSA PRIVATE KEY----- 

は、(署名しました)証明書

public static X509Certificate createX509V3Certificate(X500Principal name, BigInteger serial, Date start, Date end, PublicKey pubKey, String algorithm, PrivateKey privateKey, Map<ASN1ObjectIdentifier, Entry<Boolean, ASN1Object>> map, X509Certificate parentCert) throws IOException, OperatorCreationException, CertificateException 
{ 
    if(serial!=null && start!=null && end!=null && name!=null && pubKey!=null && algorithm!=null && privateKey!=null) 
    { 
     ContentSigner signer = new JcaContentSignerBuilder(algorithm).build(privateKey); 
     X509v3CertificateBuilder certBldr = null; 
     if(parentCert==null) 
      certBldr = new JcaX509v3CertificateBuilder(name, serial, start, end, name, pubKey); 
     else 
      certBldr = new JcaX509v3CertificateBuilder(parentCert, serial, start, end, name, pubKey); 

     if(map!=null) 
      for(ASN1ObjectIdentifier extension : map.keySet()) 
       certBldr.addExtension(extension, map.get(extension).getKey(), map.get(extension).getValue()); 

     return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBldr.build(signer)); 
    } 
    return null; 
} 
+0

あなたの最後のコードボックス内の「エントリー」とは?なぜ、entry.getKey()の代わりに 'intermediateCert'を使わないのでしょうか。 'X509CertificateGenerator'はどこから来たのですか? – gtrig

+0

エントリは実際には中間証明書ですが、私は以前に保存されたPEMファイルを読み込んでEntry(基本的に証明書とKeyPairの組み合わせ)に入れておきます。したがって、Entryは実際にはintermediateCertです。 – DokutoMekki

答えて

6

PEMファイルを作成する方法に何か問題があります。 generateSelfSignedPemX509Certificateというメソッドを使用していますが、実際には自己署名証明書を必要とせず、中間秘密鍵で署名された終了証明書が必要で、CA秘密鍵で署名された中間証明書が必要です。

さらに、証明書にはbasic constraintskey usageの内線番号が必要です。

他のエンティティによって署名された証明書(自己署名ではない)を作成するために、Bouncy Castleのこれらのメソッドを使用して「終了」証明書を作成します。

ASN1Sequence seq= 
    (ASN1Sequence) new ASN1InputStream(parentPubKey.getEncoded()).readObject(); 

    SubjectPublicKeyInfo parentPubKeyInfo = new SubjectPublicKeyInfo(seq); 

    ContentSigner signer = new JcaContentSignerBuilder(algorithm).build(parentPrivKey); 

    X509v3CertificateBuilder certBldr = 
    new JcaX509v3CertificateBuilder(
     parentCert, 
     serialNum, 
     startDate, 
     endDate, 
     distName, 
     pubKey) 
    .addExtension(
      new ASN1ObjectIdentifier("2.5.29.35"), 
      false, 
      new AuthorityKeyIdentifier(parentPubKeyInfo)) 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.19"), 
     false, 
     new BasicConstraints(false)) // true if it is allowed to sign other certs 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.15"), 
     true, 
     new X509KeyUsage(
      X509KeyUsage.digitalSignature | 
      X509KeyUsage.nonRepudiation | 
      X509KeyUsage.keyEncipherment | 
      X509KeyUsage.dataEncipherment)); 

    // Build/sign the certificate. 
    X509CertificateHolder certHolder = certBldr.build(signer); 

    X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) 
    .getCertificate(certHolder); 

CAまたは中間証明書の場合は、SubjectKeyIdentifierの内線番号を追加する必要があります。また、BasicConstraintstrueであるべき、とのKeyUsageは次のようになります。

 new X509KeyUsage(
      X509KeyUsage.keyCertSign| 
      X509KeyUsage.cRLSign)); 
+0

誤ったメソッド名についてお詫び申し上げます、私は自分の投稿を編集し、追加コードを提供しました。 – DokutoMekki

+0

それはあなたの答えは確かに正しいと思われる、私は中間証明書に欠けていた基本的な制約の拡張が必要です。これで証明書チェーンが機能し、証明書を作成するために非嫌悪な方法を使用することもできました。どうも – DokutoMekki

関連する問題