Więc mój problem jest następujący,Prawidłowo tworząc nowy certyfikat z pośredniego certyfikatu przy użyciu bouny zamek
Zasadniczo chcę, aby utworzyć łańcuch certyfikatów używając nadmuchiwany zamek (jdk16 wersji 1.46). Jestem raczej nowy w odniesieniu do dmuchanego zamku i java.security w ogóle, więc jeśli moje podejście może być całkowicie błędne, ale w każdym razie to właśnie zrobiłem:
Do tej pory jestem w stanie stworzyć samopodpisany certyfikat, którego używam jako certyfikat główny. Odbywa się to za pomocą następującego kodu:
//-----create CA certificate with key
KeyPair caPair = Signing.generateKeyPair("DSA", 1024, null, null);
to w zasadzie tworzy parę kluczy, obie opcje są zerowe dla dostawcy i bezpieczny sposób losowy, w razie potrzeby.
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);
Spowoduje to utworzenie certyfikatu z dostarczonymi atrybutami.
- seryjne = prostu bieżący czas w milisekundach
- początek = takie same jak szeregowy zasadniczo (może mieć 1 lub 2 ms różnica)
- końcowe = start + 2 dni
Mapa prostu dodaje podstawowe ograniczenie, aby ustawić certyfikat jako CA. Używam tutaj mapy, ponieważ chcę w razie potrzeby móc dodać dodatkowe rozszerzenia X509.
//-----save ca certificate in PEM format
X509CertificateGenerator.savePemX509Certificate(caCert, caPair.getPrivate(), caWriter);
Spowoduje to zapisanie certyfikatu i klucza prywatnego w pliku PEM za pomocą kreatora skaczkowego pisma kem.
Po tym plik zostanie wygenerowany i mogę zainstalować plik również (ja używam IE, a następnie zainstalować go za pośrednictwem Opcji internetowych jako zaufany CA. Certyfikat również okazał się ważny).
Następnie utworzyć certyfikat pośredni, z zastosowaniem kodu (uwagę powyższy kod znajduje się w takim samym zakresie, tak tych zmiennych są również dostępne)
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);
procedura jest Bascially takie same, jednak I dodać dodatkowe X509Extensions:
- X509Extensions.AuthorityKeyIdentifier = oznacza certyfikat CA jako półproduktów rodzica
- X509Extensions.SubjectKeyIdentifier = wykorzystuje generuje publ ic klucz do certyfikatu
Co więcej, jako wystawcę wykorzystywany jest urząd certyfikacji, a klucz prywatny ośrodka CA służy do tworzenia certyfikatu pośredniego.
To również działa i mogę zainstalować certyfikat pośredni (przy użyciu IE ponownie), jest również pokazane, że nadrzędny certyfikat jest generowany certyfikat CA i że certyfikat jest ważny.
Teraz przychodzi trudna część, w której popełniam błąd, jak sądzę. Teraz tworzę nowy certyfikat za pomocą pośredniego certyfikatu, używając następującego kodu.
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);
Zasadniczo jest to to samo, co tworzenie certyfikatu pośredniego. Jednak teraz używać następujących ustawień X509Extension:
- X509Extensions.AuthorityKeyIdentifier = ustawia certyfikat pośredni jako certyfikaty rodzica
- X509Extensions.SubjectKeyIdentifier = używa generuje klucz publiczny dla certyfikatu
Również certyfikat pośredni jest używany jako wystawca, a jego klucz prywatny służy do tworzenia certyfikatu.
Mogę również zainstalować nowy certyfikat, ale gdy sprawdzę, czy (ponownie IE), pokazuje, że certyfikat jest jednak nieważny, ponieważ "Ten urząd certyfikacji nie jest uprawniony do wydawania certyfikatów lub certyfikat nie może być używany jako koniec -jednostka."
Więc muszę jakoś włączyć certyfikat pośredni, aby móc tworzyć nowe certyfikaty, dodając niektóre KeyUsages/ExtendedKeyUsage, które zakładam.
Czy ktoś wie, w jaki sposób włączam certyfikat pośredni, aby zrobić to, co jest mi potrzebne, lub jeśli ogólnie coś robię?
EDIT 1:
Więc dobrze zapomniałem podać kod metody który stworzył certyfikat i taki, który zapisany w formacie PEM (I przemianowano go savePemX509Certificate ponieważ stary był misguiding) .
Kod do generowania certyfikatów:
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;
}
Kod dla saveing certyfikatu i klucza:
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;
}
Jak widać ja w zasadzie umieścić certyfikat i klucz w pliku, to wszystko. Wynik jest następujący i wydaje mi się dobry.
-----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-----
Więc po gtrig dostarczyła mi prawidłowy sposób, aby utworzyć certyfikat, skończyło się za pomocą tej metody, aby utworzyć albo normalny lub samo podpisane (jeśli klucz prywatny jest z tej samej pary kluczy jako klucza publicznego, is) certyfikat
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;
}
Co to jest „wejście” w ostatnim polu kodu? Dlaczego nie używać 'intermediateCert' zamiast' entry.getKey() '. Skąd pochodzi 'X509CertificateGenerator'? – gtrig
Wpis jest pośrednim certyfikatem, właśnie zauważyłem, że nadal mam stary kod, który załadował wcześniej zapisany plik PEM i umieścił go w pozycji (w zasadzie połączenie certyfikatu i klucza). Więc wpis jest w rzeczywistości pośredniCert. – DokutoMekki