问题描述
我花了很长的路使Java签名成为CSR,最后我能够做到这一点,但是openssl指出这是无效的.用openssl签名的同一CSR通过了验证步骤.
I went quite a long way to make java sign a CSR and at last I was able to do this, but openssl tells that it's not valid. The same CSR signed with openssl passes verification step.
所有都是相同的x509版本(1),没有扩展名,主题,颁发者是相同的.
All is the same x509 version (1), no extensions, Subject, Issuer are the same.
我怀疑问题与主题DN(尤其是电子邮件)或日期有关.
I suspect the problem is with subject DN (email especially) or dates.
验证:
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
文件大小相似:
1229年7月28日12:45 client.cer.pem1233年7月28日13:00 o.cer.pem
1229 Jul 28 12:45 client.cer.pem1233 Jul 28 13:00 o.cer.pem
它抱怨好像链中缺少证书,但是我看不到此类信息.
It complains like there is a missing certificate in the chain but, I don't see such information.
如何检查下一个父证书是什么?
How to check what is the next parent certificate?
有关合格证书的信息:
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
有关错误证书的信息:
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
有关CA证书的信息:
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
使用openssl签名CSR的命令
Command for signing CSR with 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
用于签署CSR的Java代码(java8上的Bouncycastle 1.54):
Java code for signing CSR (bouncycastle 1.54 on 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());
}
推荐答案
我有一个类似的示例工作
I have a similar example working
尝试用从CA获得的X500名称替换X500Name issuer =
,以避免字符出现问题
Try replacing X500Name issuer =
with the X500 name got from CA to avoid problems with characters
X500Name issuer = X500Name.getInstance(cacert.getSubjectX500Principal().getEncoded());
此外,我认为您在PEM编码之前需要此部分
Also, I think you have need this part before PEM encoding
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
signer = new JcaContentSignerBuilder("SHA1withRSA").build(cakey);
generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(signer, cacert));
generator.addCertificate(new X509CertificateHolder(certencoded));
generator.addCertificate(new X509CertificateHolder(cacert.getEncoded()));
CMSTypedData content = new CMSProcessableByteArray(certencoded);
CMSSignedData signeddata = generator.generate(content, true);
byte signedCertificate[] = signeddata.getEncoded();
这篇关于用充气城堡签名的X509证书无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!