有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用bouncy castle从证书中提取keyUsage扩展

我正在编写一个小型CA实现。可以从现有证书引导此CA。执行此操作后,我想验证输入是否具有正确的扩展名:

private static final Set<String> REQUIRED_CA_EXTENSIONS = Set.of(
        Extension.keyUsage.getId(),
        Extension.subjectKeyIdentifier.getId());

private static void validateExtensions(final X509Certificate certificate) {
    if (!CertificateExtensions.getAll(certificate).containsAll(REQUIRED_CA_EXTENSIONS)) {
        throw new RuntimeException("Attempted to create a CA from a certificate without required extensions");
    }
}

// Util method
public static Set<String> getAll(final X509Certificate certificate) {
    final Set<String> extensions = new HashSet<>();
    extensions.addAll(certificate.getCriticalExtensionOIDs());
    extensions.addAll(certificate.getNonCriticalExtensionOIDs());
    return extensions;
}

但是,这仅验证扩展是否存在。我还需要验证keyUsage扩展是否同时包含keyCertSigncRLSign才能对证书进行签名

如何使用bouncy castle和/或JCA实现这一点


共 (1) 个答案

  1. # 1 楼答案

    JCA^{}上有一种方法可以返回keyUsage扩展的位,称为^{}。根据Java文档,由返回数组中的布尔值表示的密钥用法的各个位

    也可以使用Bouncycastle库做更多的工作来实现相同的结果。我展示这两种方法是因为Bouncycastle库为检查X509证书提供了更完整的支持,因此有一个示例演示一些简单的方法非常有用,以防您想做一些更困难的事情

    请注意,在撰写本文时,这需要两个Bouncycastle库,即主提供程序/加密库和PKIX/CMS库

    import org.bouncycastle.asn1.ASN1Primitive;
    import org.bouncycastle.asn1.x509.KeyUsage;
    import org.bouncycastle.cert.X509CertificateHolder;
    
    import java.io.FileInputStream;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    public class X509CheckKeyUsage {
    
        public static void main(String[] args) throws Exception {
            FileInputStream fis = new FileInputStream("DST_X3_CA.pem"); // for example
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
    
            // check with simple JCA methods
    
            boolean [] keyUsageBools = cert.getKeyUsage();
            final int KEY_CERT_SIGN = 5;
            final int CRL_SIGN = 6;
            boolean usagesVerified = keyUsageBools[KEY_CERT_SIGN] && keyUsageBools[CRL_SIGN];
            System.out.println("key usage bits verified? " + usagesVerified);
    
            // Convert the jca x.509 cert to a bouncycastle x.509 cert, in two steps
    
            org.bouncycastle.asn1.x509.Certificate bcCert = org.bouncycastle.asn1.x509.Certificate
                    .getInstance(ASN1Primitive.fromByteArray(cert.getEncoded())); // step 1
            X509CertificateHolder bcX509Cert = new X509CertificateHolder(bcCert); // step 2
    
            // now verify keyUsage bits
    
            final int requiredKeyUsageBits = KeyUsage.keyCertSign | KeyUsage.cRLSign;
            usagesVerified = KeyUsage.fromExtensions(bcX509Cert.getExtensions()).hasUsages(requiredKeyUsageBits);
            System.out.println("key usage bits verified? " + usagesVerified);
        }
    }