通过与BouncyCastle进行CSR签名生成的证书被认为是不可信的

彼德

我正在努力解决以下问题:

我有一个使用此代码签名的CSR:

@Override
public X509Certificate signCSR( Reader pemcsr, int validityDays ) throws APIException
{
try ( PEMParser reader = new PEMParser( pemcsr ) )
{

  KeyStore keystore = getKeyStore();

  Properties cryptoProps = getCryptoProperties();

  String caKeyAlias = cryptoProps.getProperty( PROPERTY_KEYSTORE_CA_CERT_ALIAS );
  String caKeyPassword = cryptoProps.getProperty( PROPERTY_KEYSTORE_CA_CERT_PASSWORD );

  PrivateKey cakey = (PrivateKey) keystore.getKey( caKeyAlias, caKeyPassword.toCharArray() );
  X509Certificate cacert = (X509Certificate) keystore.getCertificate( caKeyAlias );

  PKCS10CertificationRequest csr = (PKCS10CertificationRequest) reader.readObject();

  AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find( "SHA1withRSA" );
  AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find( sigAlgId );
  X500Name issuer = new X500Name( cacert.getSubjectX500Principal().getName() );
  BigInteger serial = new BigInteger( 32, new SecureRandom() );
  Date from = new Date();
  Date to = new Date( System.currentTimeMillis() + ( validityDays * 86400000L ) );

  DigestCalculator digCalc = new BcDigestCalculatorProvider().get( new AlgorithmIdentifier( OIWObjectIdentifiers.idSHA1 ) );
  X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils( digCalc );

  X509v3CertificateBuilder certgen = new X509v3CertificateBuilder( issuer, serial, from, to, csr.getSubject(), csr.getSubjectPublicKeyInfo() );

  // Basic Constraints
  // certgen.addExtension( Extension.basicConstraints, true, new
  // BasicConstraints( 0 ) );

  // Subject Key Identifier
  // certgen.addExtension( Extension.subjectKeyIdentifier, false,
  // x509ExtensionUtils.createSubjectKeyIdentifier(
  // csr.getSubjectPublicKeyInfo() ) );

  // Authority Key Identifier
  // byte[] caKeyEncoded = cacert.getPublicKey().getEncoded();
  // SubjectPublicKeyInfo caSubjectPublicKeyInfo =
  // SubjectPublicKeyInfo.getInstance( caKeyEncoded );
  // certgen.addExtension( Extension.authorityKeyIdentifier, false,
  // x509ExtensionUtils.createAuthorityKeyIdentifier( caSubjectPublicKeyInfo
  // ) );

  // Key Usage
  // certgen.addExtension( Extension.keyUsage, false, new KeyUsage(
  // KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign )
  // );

  ContentSigner signer = new BcRSAContentSignerBuilder( sigAlgId, digAlgId ).build( PrivateKeyFactory.createKey( cakey.getEncoded() ) );

  // ContentSigner signer = new JcaContentSignerBuilder(
  // "SHA1WithRSAEncryption" ).setProvider( "BC" ).build( cakey );

  X509CertificateHolder holder = certgen.build( signer );

  return new JcaX509CertificateConverter().setProvider( "BC" ).getCertificate( holder );
}
catch ( NoSuchAlgorithmException | KeyStoreException | CertificateException | OperatorCreationException | UnrecoverableKeyException | CertIOException e )
{
  throw new APIException( API_ERROR_CODE.CRYPTOGRAPHY_ERROR, e );
}
catch ( IOException e )
{
  throw new APIException( API_ERROR_CODE.IO_ERROR, e );
}

}

这将成功运行。但是,当我尝试使用以下方法检查密钥时:

KeyStore ks = getKeyStore();

  TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
  trustManagerFactory.init( ks );

  for ( TrustManager trustManager : trustManagerFactory.getTrustManagers() )
  {
    if ( trustManager instanceof X509TrustManager )
    {
      X509TrustManager x509TrustManager = (X509TrustManager) trustManager;
      x509TrustManager.checkClientTrusted( new X509Certificate[] { certificate }, "RSA" );
    }
  }

...它失败,并带有CertificateException。请注意,我在这里使用VERY SAME密钥库,这意味着与我签名的CA密钥包含在其中。为什么会这样?

顺便说一句,很奇怪,当我使用Windows的证书查看器打开生成的签名证书时,它确实显示了颁发CA的名称,但其条目未显示在证书链中。似乎Windows可信度列表中不存在CA根证书,但实际上它也在那里。

甚至更陌生:如果我使用OpenSSL签署CSR,则证书链看起来还可以。我也有想法认为,通过PKCS12将CA密钥对从OpenSSL导入到Java密钥库作为中间格式是不成功的,但是实际上,如果我从Java密钥库中导出CA证书并使用Windows证书打开它查看器,它显示为受信任的...

更新:对于那些熟悉ASN.1的人,这里有两个编码的证书。一个是用BouncyCastle制作的,不受信任,另一个是用OpenSSL的同一CA密钥签名的,并且是受信任的。可以使用以下工具对其进行解码:ASN.1解码器非常感谢有人可以查看此解码数据并告诉我是什么原因导致它们之间的差异。

这是不可信的:

-----BEGIN CERTIFICATE-----
MIIC6TCCAlKgAwIBAgIESdsI/TANBgkqhkiG9w0BAQUFADCBgzEgMB4GCSqGSIb3
DQEJARYRdGVzdGNhQHRlc3RjYS5jb20xEDAOBgNVBAMMB1Rlc3QgQ0ExEDAOBgNV
BAsMB1Rlc3QgQ0ExEDAOBgNVBAoMB1Rlc3QgQ0ExDTALBgNVBAcMBFdpZW4xDTAL
BgNVBAgMBFdpZW4xCzAJBgNVBAYTAkFUMB4XDTE0MDUxOTExNTYwM1oXDTE1MDUx
OTExNTYwM1owajELMAkGA1UEBhMCVUsxCzAJBgNVBAgTAlBiMQswCQYDVQQHEwJC
cDETMBEGA1UEChMKZmdmZ2ZnZGZnZDEPMA0GA1UECxMGYWJjZGVmMRswGQYDVQQD
DBJwZXRlcnZlbG9zeV90aWdyaXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCdL7taENsONBazc2iMDV5nw9ACP5mevmnzPwOJRUcd5GlGgry/iSa3tTwL
l6Um3zNc4X0m5nVVskKeJE4dTvYFV3+vJlEKCra86yQfa6XkGllU4EG6SdG8lRhE
Btk1QbOQZKrUz77IdOWWOUvIsNxtDDQcUhnrSjSxHohdoe/yoCl+60RBdjrgUrRo
uctSHFPvVt2uZaVM2rAVovx56vvJHOag2++rcvXaOh9WHvdwRAIZt/4aOv2O4jdI
jKdRrmF8dOudjR89wIeVjX9fvyvx+hw+ZolUio9GOVKLlBcYno6lEupHLUDK9ECs
W8F6y65nYGlm9/0G0+gB7K1yy1dBAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAKJpM
7AbkWBH3ho1YV0d1glJvefQ1xaXGpDfd+Tzf3+cR1o3+YxxEyuYvBbiQ/MBxKD9/
hsFCqEWzOfu2lAZ+/6uHvt7BCEGhaLdWKXehoaIw/kEMeISIUDFbKORCsKJNbYRB
xgqBXGglTQ4gVXMDRBxzOmButN31j1VDt55gvn4=
-----END CERTIFICATE-----

这是可信任的,它是使用理论上相同的CA证书但通过OpenSSL生成的:

-----BEGIN CERTIFICATE-----
MIIC+TCCAmICAhI4MA0GCSqGSIb3DQEBBQUAMIGDMQswCQYDVQQGEwJBVDENMAsG
A1UECAwEV2llbjENMAsGA1UEBwwEV2llbjEQMA4GA1UECgwHVGVzdCBDQTEQMA4G
A1UECwwHVGVzdCBDQTEQMA4GA1UEAwwHVGVzdCBDQTEgMB4GCSqGSIb3DQEJARYR
dGVzdGNhQHRlc3RjYS5jb20wHhcNMTQwNTE0MTkzMTAzWhcNMTUwNTA5MTkzMTAz
WjCBgDELMAkGA1UEBhMCSFUxETAPBgNVBAgTCEJ1ZGFwZXN0MREwDwYDVQQHEwhC
dWRhcGVzdDEWMBQGA1UEChMNTWVyY2hhbnQgVGVzdDEWMBQGA1UECxMNTWVyY2hh
bnQgVGVzdDEbMBkGA1UEAwwScGV0ZXJ2ZWxvc3lfdGlncmlzMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1vuY4MQ5b9Jb0MiyEuCrR4E+7VgmrvEwlswO
aMIF4H6i538PwPml5dbqx/3whxR/BcQJuJYWI/Hh7xxGS7FvSQ+DNhzxv9TpECKS
/5OZNm+JikPZwTiwrS/Cf4NP+ZcXOjtVZp6ngVtTarn3NC/J7gJVYaHVVO4NbUkt
kCYhdfCXg71QiJ42RWMjMC9tJFrrlfem+SVzh8yMtUCBKm7nbMjQ6LngawjTzDK8
2Zcdqwdzvt2pcYcsYSViO5j5t/r7rIDGjRkjJqRSEiJMOvn0W+sdTdmFoZbyj7Qe
pgyCyf28uFyCO9QZro337D8klPLXaWJOwPDXXiuYOTDYAjBVbwIDAQABMA0GCSqG
SIb3DQEBBQUAA4GBAGU60GVjR+2oEiJMSe1CKU7gf+bGuxaCxXQTzVQLU652i1sp
Fv56o6jnLtw46/rQydNKX4GBH022B/BDEPAQQiQv31YKQAoWtBZod0SRonogcx7p
AULacoma9QEgHSX0l+2yEn42/qo7o0pAmmewJlsCnHVIqI0eU8x1XbCEAf53
-----END CERTIFICATE-----

更新2:

感谢Bruno的回答,证书链现在看起来不错,并生成了以下证书:

-----BEGIN CERTIFICATE-----
MIIC6TCCAlKgAwIBAgIEI2vbpTANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC
QVQxDTALBgNVBAgMBFdpZW4xDTALBgNVBAcMBFdpZW4xEDAOBgNVBAoMB1Rlc3Qg
Q0ExEDAOBgNVBAsMB1Rlc3QgQ0ExEDAOBgNVBAMMB1Rlc3QgQ0ExIDAeBgkqhkiG
9w0BCQEWEXRlc3RjYUB0ZXN0Y2EuY29tMB4XDTE0MDUyMDA3MzkyMFoXDTE1MDUy
MDA3MzkyMFowajELMAkGA1UEBhMCVUsxCzAJBgNVBAgTAlBiMQswCQYDVQQHEwJC
cDETMBEGA1UEChMKZmdmZ2ZnZGZnZDEPMA0GA1UECxMGYWJjZGVmMRswGQYDVQQD
DBJwZXRlcnZlbG9zeV90aWdyaXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCdL7taENsONBazc2iMDV5nw9ACP5mevmnzPwOJRUcd5GlGgry/iSa3tTwL
l6Um3zNc4X0m5nVVskKeJE4dTvYFV3+vJlEKCra86yQfa6XkGllU4EG6SdG8lRhE
Btk1QbOQZKrUz77IdOWWOUvIsNxtDDQcUhnrSjSxHohdoe/yoCl+60RBdjrgUrRo
uctSHFPvVt2uZaVM2rAVovx56vvJHOag2++rcvXaOh9WHvdwRAIZt/4aOv2O4jdI
jKdRrmF8dOudjR89wIeVjX9fvyvx+hw+ZolUio9GOVKLlBcYno6lEupHLUDK9ECs
W8F6y65nYGlm9/0G0+gB7K1yy1dBAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAIdFF
h6uLY7ioKQ3O0c4cZHHjRA0HTlWjih8P2xvXY/V9jF914BT7OW52UJ16tQaJlOf+
mAeeBDq9srKnkmOQp3mCejVnkyVZF8pOOzNbqSVzylt0Csg2twnxZ0NcM63Oda5b
YSQI8+arryxykLWkHWH8i/6rPCDCtbAHBo7fSeQ=
-----END CERTIFICATE-----

但是,上面的TrustManager代码将拒绝它。如果我绕开TrustManager并执行以下操作:

 KeyStore ks = getKeyStore();

  Enumeration<String> aliases = ks.aliases();

  while ( aliases.hasMoreElements() )
  {
    String alias = aliases.nextElement();
    Certificate currentCert = ks.getCertificate( alias );
    try
    {
      certificate.verify( currentCert.getPublicKey() );
      return true;
    }
    catch ( Exception e )
    {
      // the certificate cannot be verified with this key.
    }
  }

  return false;

...它过去了。有人知道为什么它在TrustManager检查中失败吗?

Ps CA证书如下所示:

-----BEGIN CERTIFICATE-----
MIICfzCCAegCCQCU+Ah6M5qQGTANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC
QVQxDTALBgNVBAgMBFdpZW4xDTALBgNVBAcMBFdpZW4xEDAOBgNVBAoMB1Rlc3Qg
Q0ExEDAOBgNVBAsMB1Rlc3QgQ0ExEDAOBgNVBAMMB1Rlc3QgQ0ExIDAeBgkqhkiG
9w0BCQEWEXRlc3RjYUB0ZXN0Y2EuY29tMB4XDTE0MDQyMzA3MjYzNFoXDTI0MDQy
MDA3MjYzNFowgYMxCzAJBgNVBAYTAkFUMQ0wCwYDVQQIDARXaWVuMQ0wCwYDVQQH
DARXaWVuMRAwDgYDVQQKDAdUZXN0IENBMRAwDgYDVQQLDAdUZXN0IENBMRAwDgYD
VQQDDAdUZXN0IENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0Y2FAdGVzdGNhLmNvbTCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAldKTo8iqF52dsOwln0Oppu+ODiaG
R4T7Znrca4Cs5FBQOmuMwqUP6ilW115p/WvkBHhm8dZyVACPKdshEfhh4VFAW5r2
mJnosYgjafQpTEv83sc938DwtK6iikZ0uvdBJKG/IuYblNq9TPMLFeTYjD8mgf9j
m6JOvA/Q9J4nRW0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQB8ACYeC+zjV/KqxPr1
cyzfJP9xfUnxDTEKUJS2YVuxJqpfbHeUtvKoN89BfY07XWdnj8cgMDfJp10Kdc2A
clwP2lVDtOgHZS07UUW98q9FKQ33mLHIn0nDKNwTo5VH8t/NJVeMFuZPAbFiI2gj
KH2sTU2GNNvKC4jHh0PS+OZFtg==
-----END CERTIFICATE-----
布鲁诺

如果您查看两个证书中的颁发者DN,则它们不匹配(来自的输出openssl x509 -text):

Issuer: C=AT, ST=Wien, L=Wien, O=Test CA, OU=Test CA, CN=Test CA/[email protected]

Issuer: [email protected], CN=Test CA, OU=Test CA, O=Test CA, L=Wien, ST=Wien, C=AT

结果,它无法将错误的颁发者与CA的主题DN相匹配。

不幸的是,X500Name issuer = new X500Name(cacert.getSubjectX500Principal().getName())并没有达到您的期望。RDN的顺序相反。通常,由于存在多种将ASN.1表示序列化为字符串的方法,因此从字符串表示重建DN可能会失败。JavaX500Principal具有多种可用格式getName(...),甚至提供了一种为字符串映射提供您自己的OID的方法(对于更加晦涩的OID)。该方法emailAddress被分离也会造成问题(注意它是用逗号或用斜杠分隔的方式)。

而是从编码形式构建X500Name,这应始终有效:

X500Name x500Name = X500Name.getInstance(cert
                        .getSubjectX500Principal().getEncoded());

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过与BouncyCastle进行CSR签名生成的证书被视为不可信

来自分类Dev

为什么OpenSSL在通过自签名不可信证书颁发证书时说该证书是可信的?

来自分类Dev

ClickOnce VSTO解决方案已使用mage.exe签名-证书不可信错误

来自分类Dev

使用BouncyCastle API生成CSR

来自分类Dev

通过openshift服务器在移动设备上的https安全证书不可信错误

来自分类Dev

Firefox表示即使证书链很好,证书也不可信

来自分类Dev

SSL为银河上托管的流星应用程序生成证书签名请求(CSR)

来自分类Dev

使用BouncyCastle为java.security.Keystore生成自签名证书的简单方法

来自分类Dev

使用BouncyCastle为java.security.Keystore生成自签名证书的简单方法

来自分类Dev

将自签名证书添加到“可信列表”

来自分类Dev

根据内容,元组可以被认为是可变的还是不可变的

来自分类Dev

BouncyCastle-TBS证书中的签名算法与外部证书不同

来自分类Dev

如何检查签名文件的数字签名是否由可信证书签名?

来自分类Dev

如何在不使用过时的BouncyCastle 1.7.0代码的情况下生成自签名证书?

来自分类Dev

PowerShell-Windows可信证书无法通过FTP验证SSL

来自分类Dev

如何以编程方式创建证书签名请求(CSR)?

来自分类Dev

如何创建证书签名请求(CSR)OWIN自托管

来自分类Dev

Java BouncyCastle ECC密钥和自签名证书

来自分类Dev

为什么foo(short int *)和bar(signed short *)被QT认为是不同的签名?

来自分类Dev

使用自签名证书通过HTTPS进行带有CORS请求的Phonegap应用

来自分类Dev

每个网站在所有浏览器上都显示不可信证书警告

来自分类Dev

Certenroll在Azure上-生成自签名证书

来自分类Dev

无法使用Powershell生成自签名证书

来自分类Dev

使用自编码签名证书进行发布

来自分类Dev

使用Java使用BouncyCastle生成X509证书

来自分类Dev

BouncyCastle-生成MS Windows可以理解的证书文件

来自分类Dev

使用Java使用BouncyCastle生成X509证书

来自分类Dev

通过https的REST API的自签名证书VS CA证书

来自分类Dev

使用Windows代码签名证书进行KEXT代码签名

Related 相关文章

  1. 1

    通过与BouncyCastle进行CSR签名生成的证书被视为不可信

  2. 2

    为什么OpenSSL在通过自签名不可信证书颁发证书时说该证书是可信的?

  3. 3

    ClickOnce VSTO解决方案已使用mage.exe签名-证书不可信错误

  4. 4

    使用BouncyCastle API生成CSR

  5. 5

    通过openshift服务器在移动设备上的https安全证书不可信错误

  6. 6

    Firefox表示即使证书链很好,证书也不可信

  7. 7

    SSL为银河上托管的流星应用程序生成证书签名请求(CSR)

  8. 8

    使用BouncyCastle为java.security.Keystore生成自签名证书的简单方法

  9. 9

    使用BouncyCastle为java.security.Keystore生成自签名证书的简单方法

  10. 10

    将自签名证书添加到“可信列表”

  11. 11

    根据内容,元组可以被认为是可变的还是不可变的

  12. 12

    BouncyCastle-TBS证书中的签名算法与外部证书不同

  13. 13

    如何检查签名文件的数字签名是否由可信证书签名?

  14. 14

    如何在不使用过时的BouncyCastle 1.7.0代码的情况下生成自签名证书?

  15. 15

    PowerShell-Windows可信证书无法通过FTP验证SSL

  16. 16

    如何以编程方式创建证书签名请求(CSR)?

  17. 17

    如何创建证书签名请求(CSR)OWIN自托管

  18. 18

    Java BouncyCastle ECC密钥和自签名证书

  19. 19

    为什么foo(short int *)和bar(signed short *)被QT认为是不同的签名?

  20. 20

    使用自签名证书通过HTTPS进行带有CORS请求的Phonegap应用

  21. 21

    每个网站在所有浏览器上都显示不可信证书警告

  22. 22

    Certenroll在Azure上-生成自签名证书

  23. 23

    无法使用Powershell生成自签名证书

  24. 24

    使用自编码签名证书进行发布

  25. 25

    使用Java使用BouncyCastle生成X509证书

  26. 26

    BouncyCastle-生成MS Windows可以理解的证书文件

  27. 27

    使用Java使用BouncyCastle生成X509证书

  28. 28

    通过https的REST API的自签名证书VS CA证书

  29. 29

    使用Windows代码签名证书进行KEXT代码签名

热门标签

归档