在 Java 中将密钥用法添加到 CertificateSigningInfo

Add Key Usage to CertificateSigningInfo in Java

我正在尝试在不使用 BouncyCastle 的情况下将密钥用法添加到 Java 中的 certificateSigningInfo。我有以下方法将创建 certificateSigningInfo 可以进一步签名以创建 PKCS#10:

public static byte[] createCertificationRequestInfo(X500Name x500Name, PublicKey publicKey) throws IOException {
    final DerOutputStream der1 = new DerOutputStream();
    der1.putInteger(BigInteger.ZERO);
    x500Name.encode(der1);
    der1.write(publicKey.getEncoded());

    // der encoded certificate request info
    final DerOutputStream der2 = new DerOutputStream();
    der2.write((byte) 48, der1);
    byte[] toReturn = der2.toByteArray();
    der2.close();
    return toReturn;
}

我正在尝试通过添加以下内容来添加密钥用法:

    KeyUsageExtension ku = new KeyUsageExtension();
    ku.set(KeyUsageExtension.NON_REPUDIATION, true);
    ku.set(KeyUsageExtension.KEY_ENCIPHERMENT, true);
    ku.set(KeyUsageExtension.DIGITAL_SIGNATURE, true);
    ku.encode(der1);

certificateSigningInfo 已创建,但无法验证,因为它有一些缺失值...

例如,创建了以下 CSR:

-----BEGIN NEW CERTIFICATE REQUEST-----
MIIErDCCApQCAQAwWjENMAsGA1UEBhMEVGVzdDENMAsGA1UECBMEVGVzdDENMAsGA1UEBxMEVGVz
dDENMAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDENMAsGA1UEAxMEVGVzdDCCAiEwDQYJKoZI
hvcNAQEBBQADggIOADCCAgkCggIAr11wXkShGHeEVRxl1K4D/7Ow8uIgVro35h/WMBKl5UWOEqBc
ajTnU9AMN+u/rVa5uRt8HcHhWF8Y4RIMoNxlMuxBu36UbxKBnPza8Y1/Dbn0HGwzematfnFYS7B7
HdyVoj6yRcSo2tM/p8bmUGpxr1NSXsEtbxVINFhuyMZnwMpuVUsqTgB58Uo/+sjGtIxDVkLaMNs4
d/HCe2rwb5rYhkvAEgXtAtoWtDD9PPZTpxhKqO+cMYGZ0HqwFyQEu687ONUpVlA068DsgzwM6oh5
w3y2OJ8PiCXW+ojqxGr5mm7ig//mbgkk7QiwoZ3taYoqAdRfGlQsOZsVzHPzAIH84CHlF2LMRcIO
M8dA3eQSopjPDPOZixo8PGQ/cYtQPgyBVGmiQt/93JQ/BAypu9olO70y91nd+cEsEzoZdGkuFnTR
KVT67ye0GnxFik6Y/VJxpE36NPbofOXVRxy8jbazJGg/AzETAGmkKXoNAbzqvVCaV2zeAOZZmTFx
rgjwQxvgW2oxpv5SCBDxtsH+/JpuqEtg5y3jzLFuibSmGs6qNDATEDIG1F1Xl0+1I6ygIE+tcycI
m/9SmlIX9UsiSEvSJe0kZOwOIrByzYhezeXdbgSHiD2WiuMe1XvXJBkqpV0wuwhw74vRKAJtz3vC
n1DNVBmBWMPWfxlVczG+HwgLBSECAwEAATAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQENBQAD
ggIBAHCEHA47S0jO7AXvF7SDXtPPV2zlgUFtvCx0DfRerElYcmQFg5ylspfvkbQnlUFOcpKgoi1/
Kgq5vchLjKVEJPJK9066NsNTRy1Ayt4f3Ne7yQ46cnrL729x7TLUcWijDgmfJE/Cp4eC0qTF87mH
rYeOK0+1azki0r6/ToM9EliDU497Tsl2CWmAJlP+hkWQRa80uPFXkEV+UH0vQwOc8mf/aW+q3LHf
BXvPHcH3J9lPtDHMZgKav7Vi4sFU8tlCzm7QE6/jU49BN+Ptgp34k8Hw+VV+4lpZX2QpkDMvaPg5
Zd7LYNGhayP//EevCftiliWsNJSHa8aA6zqYvsTnBoEPFPL4sVfXsWp18AbK294WhF5vIe+8AFks
RHMLE+Nl13SXO3wHlNDT5jXKUGFmbCOASsUjyrpfQcwVMJ0/muAX43r6zo2YatZKgmCtVrBtKVuE
U7KMJW2aEDO7ML7+47VER8r1LYWSt96OY/9Pre+UehMuDloUC5B9nSf5TKyCShnzxXoNAE7izr2A
l3x9O071c9d/pRKjUBu9Q/IrSFT/blg94zGov+9FplcXc2Ygnblt5UNjAs5XcoC6ckhGPkrcZbw6
3Qk5R9TTJGX9wpzKTFPWJF735TaFqkJNwn1U5kTKWCTgbGUi3U98gTCCV4OkeT+Fo+pWuOqz5NV5
Q778
-----END NEW CERTIFICATE REQUEST-----

感谢任何帮助。

PKCS10 type CertificationRequestInfo can't directly contain an Extension, or even Extensions (which is SEQUENCE OF Extension). Instead it can contain Attributes which is SET OF Attribute each of which is SEQUENCE of OID and SET OF values constrained by a notional InfoSet, or in the old syntax ANY DEFINED BY --metaspec. One possible Attribute is PKCS9 5.4.2 extensionRequest 包含 Extensions 可以包含 KeyUsage.

因此,要将其添加到 PKCS10,您需要如下内容。只要您使用的是未记录且可能不可靠的 sun.security 类,PKCS10 就有一个可以替换您发布的大部分代码。

import sun.security.pkcs.*;
import sun.security.pkcs10.*; // separate in j8 (and later? not checked) 
import sun.security.util.*;
import sun.security.x509.*;

    // dummy setup; replace as appropriate
    X500Name name = new X500Name("O=Widgets Inc, CN=testcert");
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
    gen.initialize(1024); KeyPair pair = gen.generateKeyPair();
    
    KeyUsageExtension ku = new KeyUsageExtension();
    ku.set(KeyUsageExtension.NON_REPUDIATION, true);
    ku.set(KeyUsageExtension.KEY_ENCIPHERMENT, true);
    ku.set(KeyUsageExtension.DIGITAL_SIGNATURE, true);
    CertificateExtensions exts = new CertificateExtensions();
    exts.set(KeyUsageExtension.IDENT,ku);
    PKCS10Attribute extreq = new PKCS10Attribute (PKCS9Attribute.EXTENSION_REQUEST_OID, exts);
    
    PKCS10 csr = new PKCS10 (pair.getPublic(), new PKCS10Attributes (new PKCS10Attribute[]{ extreq }));
    Signature signer = Signature.getInstance("SHA256withRSA"); // or adapt to key 
    signer.initSign(pair.getPrivate());
    csr.encodeAndSign(name, signer);

    // dummy output; replace 
    FileOutputStream out = new FileOutputStream ("SO49985805.der");
    out.write(csr.getEncoded()); out.close();