Извлечь расширение keyUsage из сертификата с помощью надувного замка - PullRequest
0 голосов
/ 27 января 2020

Я пишу небольшую реализацию 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, чтобы иметь возможность подписывать сертификаты.

Как я могу сделать это с помощью надувного замка и / или JCA?

1 Ответ

2 голосов
/ 28 января 2020

В JCA X509Certificate имеется метод для возврата битов расширения keyUsage, называемый просто getKeyUsage(). Отдельные биты использования ключа, представленные логическими значениями в возвращенном массиве, в соответствии с документацией Java.

Также возможно выполнить немного больше работы с использованием библиотек Bouncycastle, чтобы выполнить то же самое sh результат. Я показываю оба метода, потому что библиотеки 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);
    }
}
...