6

だから私の問題は次のとおりです、

基本的には弾む城 (jdk16 バージョン 1.46) を使用して証明書チェーンを作成したいと考えています。私は一般的に弾力のある城とjava.securityにかなり慣れていないので、私のアプローチが完全に間違っているかもしれませんが、とにかくこれは私がしたことです:

これまでのところ、ルート証明書として使用する自己署名証明書を作成できました。これは、次のコードを使用して行われます。

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

これにより、基本的にキーペアが作成されます。2 つの null オプションは、プロバイダー用と、必要に応じて安全なランダム用です。

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);

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

  • serial = 単純にミリ秒単位の現在の時刻
  • start = 基本的に serial と同じ (1 ミリ秒または 2 ミリ秒の違いがある場合があります)
  • 終了 = 開始 + 2 日

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

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

これにより、弾力性のあるカースト pem ライターを使用して、証明書と秘密鍵が 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);

手順は基本的に同じですが、X509Extensions を追加します。

  • X509Extensions.AuthorityKeyIdentifier = CA 証明書を中間の親として設定します
  • X509Extensions.SubjectKeyIdentifier = 生成された証明書の公開鍵を使用します

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

これも機能し、中間証明書をインストールできます(IEを再度使用)。親証明書が生成された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 には証明書を発行する資格がないか、証明書をエンドエンティティとして使用できない」ため、証明書が無効であることが示されます。

したがって、中間証明書が新しい証明書も作成できるようにする必要があります。

中間証明書が必要なことを実行できるようにする方法、または一般的に間違ったことをする方法を誰かが知っていますか?

編集1:

それで、証明書を作成したメソッドと PEM 形式で保存したメソッドのコードを提供するのを忘れていました (古いものは見当違いだったので、名前をsavePemX509Certificateに変更しました)。

証明書生成のコード:

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;
}

ご覧のとおり、基本的に証明書とキーをファイルに入れました。それだけです。結果は次のとおりで、私には良いようです。

-----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-----

したがって、gtrig が証明書を作成する正しい方法を提供した後、この方法を使用して、通常または自己署名 (秘密鍵が公開鍵と同じ keyPair からのものである場合) 証明書を作成することになりました。

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;
}
4

1 に答える 1