java - 使用充气城堡从证书中提取 keyUsage 扩展

标签 java x509certificate bouncycastle

我正在编写一个小型 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 才能签署证书。

如何使用充气城堡和/或 JCA 来做到这一点?

最佳答案

JCA 上有一个可用的方法 X509Certificate返回 keyUsage 扩展的位,简单地称为 getKeyUsage() 。根据 Java 文档,键用法的各个位由返回数组中的 boolean 值表示。

还可以使用 BouncycaSTLe 库做更多的工作来实现相同的结果。我展示了这两种方法,因为 BouncycaSTLe 库为检查 X509Certificate 提供了更完整的支持,因此如果您想做更困难的事情,有一个示例来说明简单的事情很有用。

请注意,截至撰写本文时,这需要两个 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);
    }
}

关于java - 使用充气城堡从证书中提取 keyUsage 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59934016/

相关文章:

Java:重载构造函数之间的选择

java - 在 Java KeyStore 中导入私钥/公钥对

Powershell "X509Certificate2Collection"异常调用 "Import"和 "3"参数 : "Cannot find the requested object

使用 BouncyCaSTLe 进行 Java 签名文件 - 使用 secret key 环创建文件签名

java - 我怎样才能快速 ((A^z1 * y^z2) mod P) mod Q

Java:使用 iText 将 2000-5000 个 PDF 合并为 1 个,产生 OutOfMemorryError

java - Jersey @PreMatching 和 1 个提供商中的名称绑定(bind)

java - 如何使用 keytool 打印证书的公钥?

C#从一个网站下载所有的https证书

java - 如何在 java 中使用 bouncy caSTLe 以 ASN1 格式导出 X509Certificate?