使用充气城堡从证书中提取 keyUsage 扩展
Extract keyUsage extension from a certificate using bouncy castle
我正在编写一个小型 CA 实现。可以从现有证书 bootstrap 此 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
扩展包含 keyCertSign
和 cRLSign
才能签署证书。
如何使用充气城堡 and/or JCA 执行此操作?
JCA X509Certificate
to return the bits of the keyUsage extension, called simply getKeyUsage()
上有一个可用的方法。根据 Java 文档,返回数组中由布尔值表示的密钥用法的各个位。
也可以使用 Bouncycastle 库做更多的工作来实现相同的结果。我展示了这两种方法,因为 Bouncycastle 库为检查 X509Certificate 提供了更完整的支持,所以如果您想做一些更困难的事情,有一个示例来说明一些简单的事情是很有用的。
请注意,在撰写本文时,这需要两个 Bouncycastle 库,主 provider/crypto 库和 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);
}
}
我正在编写一个小型 CA 实现。可以从现有证书 bootstrap 此 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
扩展包含 keyCertSign
和 cRLSign
才能签署证书。
如何使用充气城堡 and/or JCA 执行此操作?
JCA X509Certificate
to return the bits of the keyUsage extension, called simply getKeyUsage()
上有一个可用的方法。根据 Java 文档,返回数组中由布尔值表示的密钥用法的各个位。
也可以使用 Bouncycastle 库做更多的工作来实现相同的结果。我展示了这两种方法,因为 Bouncycastle 库为检查 X509Certificate 提供了更完整的支持,所以如果您想做一些更困难的事情,有一个示例来说明一些简单的事情是很有用的。
请注意,在撰写本文时,这需要两个 Bouncycastle 库,主 provider/crypto 库和 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);
}
}