PKIX路径验证失败

时间:2017-08-07 20:33:15

标签: java ssl

我试图用Java生成客户端的最终证书。当我尝试使用我回馈给客户端的证书进行身份验证时,我收到了错误消息。错误是:

引起:sun.security.validator.ValidatorException:PKIX路径验证失败:java.security.cert.CertPathValidatorException:Path不与任何信任锚链接 引起:java.security.cert.CertPathValidatorException:Path不与任何信任锚链接

目前有一个openssl实现,它使用这些扩展字段生成最终证书:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: F4 67 78 E4 40 80 FB FA   43 F3 48 3D 37 66 AC E1  .gx.@...C.H=7f..
0010: 44 3B B5 F1                                        D;..
]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:false
  PathLen: undefined
]

#3: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  clientAuth
]

#4: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Non_repudiation
  Key_Encipherment
]

#5: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 8F A6 A3 23 82 C9 20 2D   16 3E 3B 8E B5 D6 E2 8F  ...#.. -.>;.....
0010: EF 85 12 4C                                        ...L
]
]

所以我尝试在我的Java代码中做同样的事情(大部分代码都是我在网上找到的关于BouncyCastle证书生成的东西):

private static void createEndCert() throws Exception {
        X500PrivateCredential rootCredential = readRootCredentials();
        X500PrivateCredential interCredential = createIntermediateCredential(rootCredential.getPrivateKey(), rootCredential.getCertificate());
        X500PrivateCredential endCredential = createEndEntityCredential(interCredential.getPrivateKey(), interCredential.getCertificate());
        writePem(endCredential, "end.cert.pem");
    }
}

// need to use existing certs and keys 
private static X500PrivateCredential readRootCredentials() throws Exception {
    File privateKeyFile = new File(System.getProperty("user.dir") + File.separator + "mykey.pem");
    PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile));
    Object privateKeyInfo = pemParser.readObject();
    JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
    PrivateKey privateKey = converter.getPrivateKey((PrivateKeyInfo) privateKeyInfo);

    CertificateFactory certficateFactory = CertificateFactory.getInstance("X.509");
    FileInputStream fileInputStream = new FileInputStream(System.getProperty("user.dir") + File.separator + "mycert.pem");
    X509Certificate cer = (X509Certificate) certficateFactory.generateCertificate(fileInputStream);

    return new X500PrivateCredential(cer, privateKey, ROOT_ALIAS);
}

public static X500PrivateCredential createIntermediateCredential(PrivateKey caKey, X509Certificate caCert) throws Exception {
    KeyPair interPair = generateRSAKeyPair(2048);
    X509Certificate interCert = buildIntermediateCert(interPair.getPublic(), caKey, caCert);

    return new X500PrivateCredential(interCert, interPair.getPrivate(), INTERMEDIATE_ALIAS);
}

public static X500PrivateCredential createEndEntityCredential(PrivateKey caKey, X509Certificate caCert) throws Exception {
    KeyPair endPair = generateRSAKeyPair(2048);
    X509Certificate endCert = buildEndEntityCert(endPair.getPublic(), caKey, caCert);

    return new X500PrivateCredential(endCert, endPair.getPrivate(), END_ENTITY_ALIAS);
}

public static X509Certificate buildIntermediateCert(PublicKey intKey, PrivateKey caKey, X509Certificate caCert) throws Exception {
    X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
            caCert.getSubjectX500Principal(),
            BigInteger.valueOf(1),
            new Date(System.currentTimeMillis()),
            new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
            new X500Principal("CN=Test CA Certificate"),
            intKey);

    JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();

    certBuilder.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(caCert))
            .addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(intKey))
            .addExtension(Extension.basicConstraints, true, new BasicConstraints(0))
            .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));

    ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(caKey);

    return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBuilder.build(signer));
}

public static X509Certificate buildEndEntityCert(PublicKey entityKey, PrivateKey caKey, X509Certificate caCert) throws Exception {
    X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
            caCert.getSubjectX500Principal(),
            BigInteger.valueOf(1),
            new Date(System.currentTimeMillis()),
            new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
            new X500Principal("CN=Test End Entity Certificate"),
            entityKey);

    JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();

    certBuilder.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(caCert))
            .addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(entityKey))
            .addExtension(Extension.basicConstraints, true, new BasicConstraints(false))
            .addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.nonRepudiation))
            .addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));

    ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(caKey);

    return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBuilder.build(signer));
}

public static void writePEM(Object object, String filename) throws IOException {
    FileWriter fileWriter = new FileWriter(filename);
    JcaPEMWriter jcaPEMWriter = null;
    try {
        jcaPEMWriter = new JcaPEMWriter(fileWriter);
        jcaPEMWriter.writeObject(object);
    } finally {
        jcaPEMWriter.close();
        fileWriter.close();
    }
}

和我输出的扩展名如下:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 45 62 E9 13 ED 2E 3F 23   A7 A8 F1 B2 DC FE 47 5A  Eb....?#......GZ
0010: E3 5E 88 EE                                        .^..
]
[CN=ourcompany.com, OU=OurCompany]
SerialNumber: [    01]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:false
  PathLen: undefined
]

#3: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  clientAuth
]

#4: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Non_repudiation
  Key_Encipherment
]

#5: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 6F C2 81 A9 42 54 DF C2   44 1B 40 B3 A1 DD AF BD  o...BT..D.@.....
0010: 87 3D 69 0F                                        .=i.
]
]

我在第1节中看到,我在Java中创建的证书中的数据与openssl中存在的证书中的数据没有该数据。这是我的客户无法进行身份验证的原因吗?或者Java代码中有什么问题可以创建最终的crendential。感谢。

0 个答案:

没有答案