如何在 PKCS#12 上设置私钥属性(密钥用法)

如何在 PKCS#12 上设置私钥属性(密钥用法)

我使用 Java 上的 Bouncy Castle 库制作了 X509 证书。我需要为私钥设置一个密钥属性。

PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 1024
Bag Attributes
    friendlyName: ASDF
    localKeyID: XX XX XX XX
    Microsoft CSP Name: Microsoft Software Key Storage Provider  <--- (1)
Key Attributes: <No Attributes>    <--- put HERE X509v3 Key Usage: 80
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----

我需要将密钥用法设置为 80 --> X509v3 密钥用法:80。因为我使用椭圆曲线,如果没有这些属性,Windows Maquine 就无法识别。

我确实尝试过:

X509v3CertificateBuilder builder =  new JcaX509v3CertificateBuilder(
                issuerDNName, 
                serial,
                startDate, 
                endDate, 
                tX500Name, 
                pubKey);

X509KeyUsage usage = new X509KeyUsage(X509KeyUsage.digitalSignature); 
builder.addExtension(Extension.keyUsage, false, usage); 

或者

builder.addExtension(
                new ASN1ObjectIdentifier("2.5.29.15"),
                true,
                new X509KeyUsage(
                   X509KeyUsage.digitalSignature));

任何方法都行不通。我可以设置一个 Bag 属性 (1),这样:

PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privateKey;//pbeWithSHA1And3-KeyTripleDES-CBC
        bagAttr.setBagAttribute(
                MicrosoftObjectIdentifiers.microsoft.branch("17").branch("1"),// this OID corresponds to: 1.3.6.1.4.1.311.17.1
                new DERBMPString("Microsoft Software Key Storage Provider"));

存在一个 PrivateKeyInfo 类,但我不知道如何使用它。

如果我使用 openssl,我需要—密钥签名选项。

openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -name "MY CERTIFICATE" -certfile demoCA/cacert.pem -out mycert.p12 -keysig

OpenSSL文档

-keyex|—密钥签名 指定私钥用于密钥交换或仅用于签名。此选项仅由 MSIE 和类似的 MS 软件解释。通常,“出口级”软件只允许使用 512 位 RSA 密钥进行加密,但允许使用任意长度的密钥进行签名。-keysig 选项标记密钥仅用于签名。仅签名密钥可用于 S/MIME 签名、Authenticode(ActiveX 控件签名)和 SSL 客户端身份验证,但是由于存在错误,只有 MSIE 5.0 及更高版本支持使用仅签名密钥进行 SSL 客户端身份验证。

结果:

PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
Bag Attributes
    localKeyID: XX XX XX XX
    friendlyName: ASDF
    Microsoft CSP Name: ECDSA_P256#Microsoft Software key Service Provider
Key Attributes
    X509v3 Key Usage: 80     <-- This
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----

谢谢!

答案1

下面给出了带有密钥属性的稍微修改过的 pkcs12 创建代码。

private static void createPKCS12File(String alias, PrivateKey key,
X509Certificate cert, char[] password, OutputStream pfxOut)
throws Exception
{
    PrivateKeyInfo pki = PrivateKeyInfo.getInstance(key.getEncoded());
    X509KeyUsage usage = new X509KeyUsage(X509KeyUsage.digitalSignature);
    DERSet usageSet = new DERSet(usage);
    DERSequence attrib = new DERSequence(new ASN1Encodable[]
        {new ASN1ObjectIdentifier("2.5.29.15"), usageSet});
    pki = new PrivateKeyInfo(pki.getPrivateKeyAlgorithm(),
        pki.parsePrivateKey(), new DLSet(attrib));

    OutputEncryptor encOut = new JcePKCSPBEOutputEncryptorBuilder(
        NISTObjectIdentifiers.id_aes256_CBC).setProvider("BC").build(
        password);
    PKCS12SafeBagBuilder certBuilder = new JcaPKCS12SafeBagBuilder(
        cert);
    certBuilder.addBagAttribute(
        PKCS12SafeBag.friendlyNameAttribute, new DERBMPString(alias));

    JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
    SubjectKeyIdentifier pubKeyId = extUtils.createSubjectKeyIdentifier(
        cert.getPublicKey());
    certBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute,
        pubKeyId);
    PKCS12SafeBagBuilder keyBagBuilder = new PKCS12SafeBagBuilder(pki,
        encOut);
    keyBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute,
        new DERBMPString(alias));
    keyBagBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute,
        pubKeyId);
    keyBagBuilder.addBagAttribute(new ASN1ObjectIdentifier(
        "1.3.6.1.4.1.311.17.1"),
        new DERBMPString("Microsoft Software Key Storage Provider"));
    PKCS12PfxPduBuilder builder = new PKCS12PfxPduBuilder();
    builder.addData(keyBagBuilder.build());
    builder.addEncryptedData(new JcePKCSPBEOutputEncryptorBuilder(
        PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC).
        setProvider("BC").build(password),
        new PKCS12SafeBag[]{certBuilder.build()});
    PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(
        NISTObjectIdentifiers.id_sha256), password);
    pfxOut.write(pfx.getEncoded(ASN1Encoding.DL));
    pfxOut.flush();
}

相关内容