Ich ging einen ziemlich langen Weg, um Java ein CSR zu unterzeichnen und schließlich konnte ich dies tun, aber openssl sagt, dass es nicht gültig ist. Derselbe CSR, der mit openssl signiert wurde, besteht den Bestätigungsschritt.X509 Zertifikat mit Hüpfburg unterzeichnet ist nicht gültig
Alle ist die gleiche x509-Version (1), keine Erweiterungen, Betreff, Aussteller sind gleich.
Ich vermute, das Problem ist mit Thema DN (insbesondere E-Mail) oder Daten.
Überprüfung:
openssl verify -verbose -CAfile src/test/resources/ca.cer.pem o.cer.pem
o.cer.pem: OK
openssl verify -verbose -CAfile src/test/resources/ca.cer.pem client.cer.pem
client.cer.pem: C = RU, ST = Moscow, L = Moscow, O = Hoofs, OU = IT, CN = Danee Yaitskov
error 20 at 0 depth lookup:unable to get local issuer certificate
Dateigrößen sind ähnlich:
1229 28 Jul 12.45 client.cer.pem 1233 28. Juli 13.00 Uhr o.cer.pem
Es beschwert sich, als gäbe es ein fehlendes Zertifikat in der Kette, aber solche Informationen sehe ich nicht.
Wie überprüft man, was das nächste Elternzertifikat ist?
Info über gutes Zertifikat:
openssl x509 -in o.cer.pem -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1192228 (0x123124)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=www.hoofs.com/[email protected]
Validity
Not Before: Jul 28 11:00:01 2016 GMT
Not After : Jul 28 11:00:01 2017 GMT
Subject: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=Danee Yaitskov
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c2:94:04:69:58:3c:90:a9:0e:7e:23:78:9a:7c:
30:09:f1:5b:cf:0f:3c:d9:63:48:fb:97:77:2a:67:
85:20:30:a0:d6:57:4d:0c:55:5b:53:97:7b:5c:2f:
f5:6d:49:84:7d:59:6b:eb:3d:9b:84:ac:2c:bc:56:
1f:24:d4:d3:6b:be:0c:53:c4:e6:57:85:1e:95:9e:
37:9d:58:e1:e3:d5:5f:17:99:6c:69:2a:7e:9a:a5:
f4:11:69:54:b5:eb:71:ea:5d:a5:9f:b2:38:b7:47:
33:42:87:b5:83:64:0b:8c:d1:3c:2b:a4:a8:fd:6a:
1e:5c:1e:eb:c3:c2:f7:c6:10:95:65:b9:f4:15:97:
2a:88:c6:22:53:f5:63:92:89:05:ce:91:af:ee:4f:
4e:bb:a8:03:3c:ed:5b:0f:35:45:45:c3:a1:6f:af:
aa:87:21:94:ba:4d:63:25:fa:eb:65:1e:e0:34:75:
90:04:d4:71:4f:54:ed:e9:52:a1:b8:52:45:3b:03:
9f:15:80:3f:e6:d8:0d:32:55:df:e0:ea:78:34:e0:
30:64:dd:7c:77:b4:03:ce:d1:0d:ac:24:a7:b4:08:
63:3d:1a:9e:54:b1:2e:b1:b0:1d:24:b2:a6:9b:8d:
dc:3f:bd:ae:59:72:01:07:f8:e9:e8:c8:73:78:5c:
0c:b1
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
a3:88:4c:84:5a:af:e3:35:6c:3d:a8:05:9b:7e:f5:a0:a3:b1:
79:de:31:db:1e:ca:ce:d9:69:aa:88:8f:fb:78:04:aa:3b:c4:
41:ed:13:77:3b:17:b5:62:9b:da:54:92:25:0e:46:71:a0:f1:
43:28:d4:81:3f:be:a6:ce:53:3f:03:70:13:55:44:5f:f2:a5:
ab:b0:d5:1f:84:70:84:f9:b5:74:cd:4a:f6:fc:bd:f8:71:bc:
42:66:e0:a4:ec:4a:b6:26:e9:f9:fa:5e:67:fe:73:07:10:7d:
e2:02:d7:a6:30:8e:20:fb:0c:f9:f6:3e:6e:80:87:6f:3b:30:
c3:07:3d:af:ee:f7:e2:cc:0f:7d:71:39:fc:30:1a:15:1c:1f:
7f:4a:7e:9d:80:a4:1a:8f:f5:d9:e9:0b:95:c9:3c:5c:88:6d:
a7:66:2b:dc:b0:03:6e:f2:c5:b2:7a:85:35:0b:d6:8f:53:79:
d7:13:28:3f:fb:2c:59:9c:69:df:8a:dd:96:f6:bd:b8:78:5e:
b7:84:c5:48:d2:cf:4f:e8:a4:a8:d7:f5:91:d2:8c:94:95:9f:
a5:b9:10:c2:87:4b:ee:fa:2d:1c:bb:8f:37:f6:56:20:1c:a5:
aa:e9:77:bf:c4:29:92:67:14:81:76:43:e9:47:dd:5b:7d:9e:
69:7a:73:ec
Info über schlechtes Zertifikat:
openssl x509 -in client.cer.pem -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 362342824 (0x1598e9a8)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=www.hoofs.com/[email protected]
Validity
Not Before: Jul 28 10:45:12 2015 GMT
Not After : Jul 28 10:45:12 2026 GMT
Subject: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=Danee Yaitskov
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c2:94:04:69:58:3c:90:a9:0e:7e:23:78:9a:7c:
30:09:f1:5b:cf:0f:3c:d9:63:48:fb:97:77:2a:67:
85:20:30:a0:d6:57:4d:0c:55:5b:53:97:7b:5c:2f:
f5:6d:49:84:7d:59:6b:eb:3d:9b:84:ac:2c:bc:56:
1f:24:d4:d3:6b:be:0c:53:c4:e6:57:85:1e:95:9e:
37:9d:58:e1:e3:d5:5f:17:99:6c:69:2a:7e:9a:a5:
f4:11:69:54:b5:eb:71:ea:5d:a5:9f:b2:38:b7:47:
33:42:87:b5:83:64:0b:8c:d1:3c:2b:a4:a8:fd:6a:
1e:5c:1e:eb:c3:c2:f7:c6:10:95:65:b9:f4:15:97:
2a:88:c6:22:53:f5:63:92:89:05:ce:91:af:ee:4f:
4e:bb:a8:03:3c:ed:5b:0f:35:45:45:c3:a1:6f:af:
aa:87:21:94:ba:4d:63:25:fa:eb:65:1e:e0:34:75:
90:04:d4:71:4f:54:ed:e9:52:a1:b8:52:45:3b:03:
9f:15:80:3f:e6:d8:0d:32:55:df:e0:ea:78:34:e0:
30:64:dd:7c:77:b4:03:ce:d1:0d:ac:24:a7:b4:08:
63:3d:1a:9e:54:b1:2e:b1:b0:1d:24:b2:a6:9b:8d:
dc:3f:bd:ae:59:72:01:07:f8:e9:e8:c8:73:78:5c:
0c:b1
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
71:17:8f:bb:09:05:91:0e:47:ba:f8:53:28:e3:d3:e3:b2:94:
02:71:b1:d1:93:45:d7:a0:f2:be:1f:4d:a3:18:95:35:23:6a:
1c:1d:4b:5f:60:cf:1c:93:22:1a:1b:4d:6c:e3:14:bc:7f:25:
85:24:a5:00:fb:ed:36:23:ea:b2:51:6d:8a:f2:58:07:e9:5f:
89:7e:8c:59:d2:1d:7c:85:69:bf:97:3f:f4:8f:3d:b4:21:4e:
c3:ad:1a:bd:fa:22:03:85:a3:d2:9c:76:71:58:43:4e:3f:d8:
d2:ec:8e:17:d0:53:65:c1:b7:82:38:fc:73:53:a1:80:38:1d:
89:f6:e2:48:d8:ea:a6:f6:b4:46:95:2e:cb:36:b6:e5:c2:02:
3f:bc:b2:82:a8:2e:02:7b:56:8e:59:c4:ee:1e:a5:40:bf:38:
b9:28:e7:37:2c:95:ce:2d:0b:b1:45:43:9b:49:fe:ec:37:49:
bd:f6:1e:7a:d2:2e:5c:8d:bc:00:e6:aa:96:16:83:72:8d:71:
13:33:1c:8f:8c:c7:dd:e0:99:b3:98:ac:7d:52:83:00:34:0f:
35:7a:55:d0:05:57:6c:a4:e0:5e:6d:58:a9:eb:79:e2:ae:e0:
13:87:32:e4:78:eb:a7:31:64:bf:c4:13:6d:2d:85:a2:67:ec:
62:d8:98:cb
Info über CA-Zertifikat:
openssl x509 -in src/test/resources/ca.cer.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 15043747854009729194 (0xd0c620f7d0cb80aa)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=www.hoofs.com/[email protected]
Validity
Not Before: Apr 7 08:18:18 2016 GMT
Not After : Apr 7 08:18:18 2017 GMT
Subject: C=RU, ST=Moscow, L=Moscow, O=Hoofs, OU=IT, CN=www.hoofs.com/[email protected]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d4:7a:59:42:12:40:fb:4f:02:09:af:cf:6e:a1:
56:1e:4a:1d:9b:8e:5c:4a:53:5b:63:34:f1:ac:5c:
4c:de:e8:2c:f0:6b:14:58:ec:64:a7:9f:1d:54:4a:
36:b7:11:4f:65:d6:bd:9b:9a:b5:b7:df:d7:41:e1:
f0:2e:8f:c8:88:d5:bc:56:ab:f5:cd:fc:f5:0c:0f:
25:a5:c9:78:cc:e3:74:86:3e:58:51:ce:18:d4:9c:
61:85:5f:de:08:2c:65:17:a2:ad:0e:05:63:92:58:
c4:76:ee:02:2c:68:41:4e:a9:8f:8f:2e:98:82:47:
39:eb:60:a2:5c:ee:0a:55:23:5e:d6:cd:d2:29:94:
0d:e0:cd:82:b0:af:83:61:93:22:99:b1:5c:f2:f8:
3b:71:30:5b:26:46:3e:15:d0:26:d7:70:ae:34:31:
35:a4:39:f7:dd:e4:99:4f:68:42:78:9a:90:70:4a:
8d:0f:08:2d:80:b2:2a:23:5e:55:b9:28:52:dd:ce:
15:bd:77:41:66:3f:1b:dc:9f:47:89:b3:e2:0d:f0:
25:5e:5e:47:d4:f9:e9:f6:fb:8e:08:7e:52:5f:bd:
bd:4d:2a:bf:ed:08:6a:7f:4c:32:21:c6:c0:6a:53:
84:f8:1d:37:47:0d:93:e7:90:90:2b:7c:03:db:7a:
40:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
B7:2A:B2:C4:63:E8:E3:D5:7A:A7:30:4D:5B:E8:C3:2D:5A:72:BC:DE
X509v3 Authority Key Identifier:
keyid:B7:2A:B2:C4:63:E8:E3:D5:7A:A7:30:4D:5B:E8:C3:2D:5A:72:BC:DE
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
3a:74:2d:13:96:06:26:35:7d:cc:44:28:d2:9a:47:e4:08:9e:
c5:ef:91:b7:6f:66:e1:bd:96:92:28:b1:13:3b:f3:2d:57:4f:
85:c6:e8:7d:53:3f:ba:c3:78:80:da:4e:ba:a8:85:e2:22:b2:
19:5d:62:2a:7d:ed:48:ab:b4:22:7a:9a:f1:83:b8:04:0d:87:
dc:9e:61:fd:e7:e8:2e:c4:12:6e:b9:6b:b0:14:79:35:86:91:
e8:f0:de:00:b8:bd:7e:d0:d1:4c:33:db:c3:f0:05:b7:06:2a:
21:33:4b:82:e5:74:7d:65:d8:ce:81:7f:f3:6f:03:c8:5c:aa:
de:fd:24:46:aa:20:95:d6:bc:91:ee:f9:ec:d0:c8:e5:9e:8d:
1c:44:1b:6c:05:4a:a9:bd:19:86:61:f0:5f:75:12:46:28:80:
29:79:c2:1e:e8:1c:e7:48:38:7d:7a:40:c8:ca:c9:4d:b1:a9:
5c:53:90:33:4f:13:70:93:97:73:0a:84:ac:31:0e:8e:a6:cb:
c4:53:b7:c8:0c:9e:15:22:11:0a:b8:db:5a:95:6a:d2:26:49:
e4:4e:3a:c0:9f:47:95:29:db:84:bc:6a:da:25:ba:96:05:33:
d6:1c:23:5a:76:36:75:4f:ce:19:f8:ff:27:5e:e0:4f:c3:77:
2a:63:63:6e
Befehl zur Unterzeichnung CSR mit openssl
openssl x509 -req -days ${DAYS:-365} -in src/test/resources/client.csr -CA src/test/resources/ca.cer.pem -CAkey src/test/resources/ca.key.pem -out o.cer.pem -CAserial serial
Java-Code für die Unterzeichnung CSR (bouncycastle 1,54 auf java8):
@Test
@SneakyThrows
public void sign() {
Security.addProvider(new BouncyCastleProvider());
X509Certificate caCert = loadCert("/ca.cer.pem");
PrivateKey caKey = readPrivateKey("/ca.key.pem");
try (InputStream csr = getClass().getResourceAsStream("/client.csr")) {
String cert = signCSR(new InputStreamReader(csr), caKey, caCert);
assertNotNull(cert);
Files.write(Paths.get("client.cer.pem"), cert.getBytes());
}
}
@SneakyThrows
public byte[] readFile(String path) {
try (InputStream keyStream = getClass().getResourceAsStream(path)) {
return IOUtils.toByteArray(keyStream);
}
}
public static final char[] PASSWORD = "12312312".toCharArray();
@SneakyThrows
public PrivateKey readPrivateKey(String privateKeyPath) {
PEMParser keyReader = new PEMParser(new InputStreamReader(getClass()
.getResourceAsStream(privateKeyPath)));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
converter.setProvider(new BouncyCastleProvider());
PKCS8EncryptedPrivateKeyInfo keyPair = (PKCS8EncryptedPrivateKeyInfo) keyReader.readObject();
final JceOpenSSLPKCS8DecryptorProviderBuilder jceOpenSSLPKCS8DecryptorProviderBuilder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
jceOpenSSLPKCS8DecryptorProviderBuilder.setProvider("BC");
InputDecryptorProvider pkcs8Prov = jceOpenSSLPKCS8DecryptorProviderBuilder.build(PASSWORD);
PrivateKeyInfo pk = keyPair.decryptPrivateKeyInfo(pkcs8Prov);
return converter.getPrivateKey(pk);
}
@SneakyThrows
public X509Certificate loadCert(String path) {
try (InputStream caStream = getClass().getResourceAsStream(path)) {
X509CertificateHolder holder = (X509CertificateHolder) new PEMParser(
new InputStreamReader(caStream))
.readObject();
CertificateFactory cf = CertificateFactory.getInstance("X509",
new BouncyCastleProvider());
return (X509Certificate) cf.generateCertificate(
new ByteArrayInputStream(holder.getEncoded()));
}
}
public static String signCSR(Reader pemcsr, PrivateKey cakey, X509Certificate cacert) throws Exception {
PEMParser reader = new PEMParser(pemcsr);
PKCS10CertificationRequest csr = (PKCS10CertificationRequest) reader.readObject();
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
X500Name issuer = new X500NameBuilder(BCStrictStyle.INSTANCE)
.addRDN(BCStrictStyle.C, "RU")
.addRDN(BCStyle.ST, "Moscow")
.addRDN(BCStyle.L, "Moscow")
.addRDN(BCStyle.O, "Hoofs")
.addRDN(BCStyle.OU, "IT")
.addRDN(BCStyle.CN, "www.hoofs.com/[email protected]")
.build();
BigInteger serial = new BigInteger(32, new SecureRandom());
Date from = new DateTime().minusYears(1).toDate();
Date to = new DateTime().plusYears(10).toDate();
X509v1CertificateBuilder certBuilder = new X509v1CertificateBuilder(
issuer, serial,
from, to, csr.getSubject(), csr.getSubjectPublicKeyInfo());
ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(cakey.getEncoded()));
X509CertificateHolder holder = certBuilder.build(signer);
byte[] certencoded = holder.toASN1Structure().getEncoded();
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write("-----BEGIN CERTIFICATE-----\n".getBytes());
out.write(java.util.Base64.getMimeEncoder(64, "\n".getBytes()).encode(certencoded));
out.write("\n-----END CERTIFICATE-----\n".getBytes());
out.close();
return new String(out.toByteArray());
}
*** 'CN = www.hoofs.com' *** ist zwielichtig. DNS-Namen gehen in den Subject Alt Name (SAN). Wenn ein DNS-Name im CN ist, muss er auch im SAN vorhanden sein (yep, Sie müssen ihn zweimal auflisten, daher ist es einfacher, ihn im SAN zu platzieren). Die Regeln und Gründe dafür finden Sie unter [Wie unterschreiben Sie eine Zertifikatsignierungsanforderung mit Ihrer Zertifizierungsstelle?] (Http://stackoverflow.com/a/21340898/608639) und [Wie erstelle ich ein selbstsigniertes Zertifikat mit openssl? ] (http://stackoverflow.com/q/10175812/608639) – jww
* "So überprüfen Sie, welches das nächste übergeordnete Zertifikat ist ..." * - Der Aussteller des Betreffenden ist das nächste übergeordnete Zertifikat. Gehen Sie die Kette/den Pfad hinauf, bis Sie einen Vertrauensanker treffen. Wenn der Betreff und der Aussteller identisch sind, haben Sie den selbstsignierten Stamm gefunden. Es ist der letzte Ort, wo Sie Ihr Vertrauen verwurzeln können. Es ist in Ordnung, Root-Vertrauen früher in einem Zwischenzertifikat. – jww