【问题标题】:Cannot open PKCS12 store because of password由于密码,无法打开 PKCS12 商店
【发布时间】:2019-05-09 07:43:35
【问题描述】:

在充气城堡示例中,我找到了以下代码:

package crypto;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.ContentInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.operator.bc.BcDefaultDigestProvider;
import org.bouncycastle.pkcs.PKCS12PfxPdu;
import org.bouncycastle.pkcs.PKCS12PfxPduBuilder;
import org.bouncycastle.pkcs.PKCS12SafeBag;
import org.bouncycastle.pkcs.PKCS12SafeBagBuilder;
import org.bouncycastle.pkcs.PKCS12SafeBagFactory;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.bc.BcPKCS12MacCalculatorBuilderProvider;
import org.bouncycastle.pkcs.jcajce.JcaPKCS12SafeBagBuilder;
import org.bouncycastle.pkcs.jcajce.JcePKCS12MacCalculatorBuilder;
import org.bouncycastle.pkcs.jcajce.JcePKCSPBEInputDecryptorProviderBuilder;
import org.bouncycastle.pkcs.jcajce.JcePKCSPBEOutputEncryptorBuilder;
import org.bouncycastle.util.io.Streams;


public class PKCS12 {
    public static void main(String[] args)
            throws Exception
    {
        Security.addProvider(new BouncyCastleProvider());

        KeyStore credentials = JcaUtils.createCredentials();
        PrivateKey key = (PrivateKey)credentials.getKey(JcaUtils.END_ENTITY_ALIAS, JcaUtils.KEY_PASSWD);
        Certificate[] chain = credentials.getCertificateChain(JcaUtils.END_ENTITY_ALIAS);

        createPKCS12File(new FileOutputStream("id.p12"), key, chain);

        //
        // first do a "blow by blow" read of the PKCS#12 file.
        //
        PKCS12PfxPdu pfx = readPKCS12File(new FileInputStream("id.p12"));

        //
        // or alternately just load it up using a KeyStore
        //
        KeyStore pkcs12Store = KeyStore.getInstance("PKCS12", "BC");

        pkcs12Store.load(new FileInputStream("id.p12"), JcaUtils.KEY_PASSWD);

        System.out.println("########## KeyStore Dump");

        for (Enumeration en = pkcs12Store.aliases(); en.hasMoreElements();)
        {
            String alias = (String)en.nextElement();

            if (pkcs12Store.isCertificateEntry(alias))
            {
                System.out.println("Certificate Entry: " + alias + ", Subject: " + (((X509Certificate)pkcs12Store.getCertificate(alias)).getSubjectDN()));
            }
            else if (pkcs12Store.isKeyEntry(alias))
            {
                System.out.println("Key Entry: " + alias + ", Subject: " + (((X509Certificate)pkcs12Store.getCertificate(alias)).getSubjectDN()));
            }
        }

        System.out.println();
    }

    private static void createPKCS12File(OutputStream pfxOut, PrivateKey key, Certificate[] chain)
            throws Exception
    {
        OutputEncryptor encOut = new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC).setProvider("BC").build(JcaUtils.KEY_PASSWD);

        PKCS12SafeBagBuilder taCertBagBuilder = new JcaPKCS12SafeBagBuilder((X509Certificate)chain[2]);

        taCertBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("Bouncy Primary Certificate"));

        PKCS12SafeBagBuilder caCertBagBuilder = new JcaPKCS12SafeBagBuilder((X509Certificate)chain[1]);

        caCertBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("Bouncy Intermediate Certificate"));

        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
        PKCS12SafeBagBuilder eeCertBagBuilder = new JcaPKCS12SafeBagBuilder((X509Certificate)chain[0]);

        eeCertBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("Eric's Key"));
        SubjectKeyIdentifier pubKeyId = extUtils.createSubjectKeyIdentifier(chain[0].getPublicKey());
        eeCertBagBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute, pubKeyId);

        PKCS12SafeBagBuilder keyBagBuilder = new JcaPKCS12SafeBagBuilder(key, encOut);

        keyBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("Eric's Key"));
        keyBagBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute, pubKeyId);

        PKCS12PfxPduBuilder builder = new PKCS12PfxPduBuilder();

        builder.addData(keyBagBuilder.build());

        builder.addEncryptedData(new JcePKCSPBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC).setProvider("BC").build(JcaUtils.KEY_PASSWD), new PKCS12SafeBag[]{eeCertBagBuilder.build(), caCertBagBuilder.build(), taCertBagBuilder.build()});

        PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(NISTObjectIdentifiers.id_sha256), JcaUtils.KEY_PASSWD);

        // make sure we don't include indefinite length encoding
        pfxOut.write(pfx.getEncoded(ASN1Encoding.DL));

        pfxOut.close();
    }

    private static PKCS12PfxPdu readPKCS12File(InputStream pfxIn)
            throws Exception
    {
        PKCS12PfxPdu pfx = new PKCS12PfxPdu(Streams.readAll(pfxIn));

        if (!pfx.isMacValid(new BcPKCS12MacCalculatorBuilderProvider(BcDefaultDigestProvider.INSTANCE), JcaUtils.KEY_PASSWD))
        {
            System.err.println("PKCS#12 MAC test failed!");
        }

        ContentInfo[] infos = pfx.getContentInfos();

        Map certMap = new HashMap();
        Map certKeyIds = new HashMap();
        Map privKeyMap = new HashMap();
        Map privKeyIds = new HashMap();

        InputDecryptorProvider inputDecryptorProvider = new JcePKCSPBEInputDecryptorProviderBuilder()
                .setProvider("BC").build(JcaUtils.KEY_PASSWD);
        JcaX509CertificateConverter  jcaConverter = new JcaX509CertificateConverter().setProvider("BC");

        for (int i = 0; i != infos.length; i++)
        {
            if (infos[i].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
            {
                PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i], inputDecryptorProvider);

                PKCS12SafeBag[] bags = dataFact.getSafeBags();

                for (int b = 0; b != bags.length; b++)
                {
                    PKCS12SafeBag bag = bags[b];

                    X509CertificateHolder certHldr = (X509CertificateHolder)bag.getBagValue();
                    X509Certificate       cert = jcaConverter.getCertificate(certHldr);

                    Attribute[] attributes = bag.getAttributes();
                    for (int a = 0; a != attributes.length; a++)
                    {
                        Attribute attr = attributes[a];

                        if (attr.getAttrType().equals(PKCS12SafeBag.friendlyNameAttribute))
                        {
                            certMap.put(((DERBMPString)attr.getAttributeValues()[0]).getString(), cert);
                        }
                        else if (attr.getAttrType().equals(PKCS12SafeBag.localKeyIdAttribute))
                        {
                            certKeyIds.put(attr.getAttributeValues()[0], cert);
                        }
                    }
                }
            }
            else
            {
                PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i]);

                PKCS12SafeBag[] bags = dataFact.getSafeBags();

                PKCS8EncryptedPrivateKeyInfo encInfo = (PKCS8EncryptedPrivateKeyInfo)bags[0].getBagValue();
                PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider);

                KeyFactory keyFact = KeyFactory .getInstance(info.getPrivateKeyAlgorithm().getAlgorithm().getId(), "BC");
                PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(info.getEncoded()));

                Attribute[] attributes = bags[0].getAttributes();
                for (int a = 0; a != attributes.length; a++)
                {
                    Attribute attr = attributes[a];

                    if (attr.getAttrType().equals(PKCS12SafeBag.friendlyNameAttribute))
                    {
                        privKeyMap.put(((DERBMPString)attr.getAttributeValues()[0]).getString(), privKey);
                    }
                    else if (attr.getAttrType().equals(PKCS12SafeBag.localKeyIdAttribute))
                    {
                        privKeyIds.put(privKey, attr.getAttributeValues()[0]);
                    }
                }
            }
        }

        System.out.println("########## PFX Dump");
        for (Iterator it = privKeyMap.keySet().iterator(); it.hasNext();)
        {
            String alias = (String)it.next();

            System.out.println("Key Entry: " + alias + ", Subject: " + (((X509Certificate)certKeyIds.get(privKeyIds.get(privKeyMap.get(alias)))).getSubjectDN()));
        }

        for (Iterator it = certMap.keySet().iterator(); it.hasNext();)
        {
            String alias = (String)it.next();

            System.out.println("Certificate Entry: " + alias + ", Subject: " + (((X509Certificate)certMap.get(alias)).getSubjectDN()));
        }
        System.out.println();

        return pfx;
    }
}

当我使用此代码编写 p12 时,我尝试使用 openssl 或钥匙串打开它,并提示我输入密码。我用他们的密码

public static char[] KEY_PASSWD = "keyPassword".toCharArray();

尝试打开P12,但它不起作用。另外,当我按原样运行这个主函数时,这条线会被执行

System.err.println("PKCS#12 MAC test failed!");

为了在 p12 上正确输入密码,他们的示例有什么问题吗?我基本上是在尝试做相当于

openssl pkcs12 -export -des3

如果有人也有其他想法,在 Java 中使用 Bouncy Castle。

编辑

查看可供选择的 NISTObjectIdentifiers,我没有看到 p12pbmac/sha1。这是我看到的:

public interface NISTObjectIdentifiers {
    ASN1ObjectIdentifier nistAlgorithm = new ASN1ObjectIdentifier("2.16.840.1.101.3.4");
    ASN1ObjectIdentifier hashAlgs = nistAlgorithm.branch("2");
    ASN1ObjectIdentifier id_sha256 = hashAlgs.branch("1");
    ASN1ObjectIdentifier id_sha384 = hashAlgs.branch("2");
    ASN1ObjectIdentifier id_sha512 = hashAlgs.branch("3");
    ASN1ObjectIdentifier id_sha224 = hashAlgs.branch("4");
    ASN1ObjectIdentifier id_sha512_224 = hashAlgs.branch("5");
    ASN1ObjectIdentifier id_sha512_256 = hashAlgs.branch("6");
    ASN1ObjectIdentifier id_sha3_224 = hashAlgs.branch("7");
    ASN1ObjectIdentifier id_sha3_256 = hashAlgs.branch("8");
    ASN1ObjectIdentifier id_sha3_384 = hashAlgs.branch("9");
    ASN1ObjectIdentifier id_sha3_512 = hashAlgs.branch("10");
    ASN1ObjectIdentifier id_shake128 = hashAlgs.branch("11");
    ASN1ObjectIdentifier id_shake256 = hashAlgs.branch("12");
    ASN1ObjectIdentifier id_hmacWithSHA3_224 = hashAlgs.branch("13");
    ASN1ObjectIdentifier id_hmacWithSHA3_256 = hashAlgs.branch("14");
    ASN1ObjectIdentifier id_hmacWithSHA3_384 = hashAlgs.branch("15");
    ASN1ObjectIdentifier id_hmacWithSHA3_512 = hashAlgs.branch("16");
    ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
    ASN1ObjectIdentifier id_aes128_ECB = aes.branch("1");
    ASN1ObjectIdentifier id_aes128_CBC = aes.branch("2");
    ASN1ObjectIdentifier id_aes128_OFB = aes.branch("3");
    ASN1ObjectIdentifier id_aes128_CFB = aes.branch("4");
    ASN1ObjectIdentifier id_aes128_wrap = aes.branch("5");
    ASN1ObjectIdentifier id_aes128_GCM = aes.branch("6");
    ASN1ObjectIdentifier id_aes128_CCM = aes.branch("7");
    ASN1ObjectIdentifier id_aes128_wrap_pad = aes.branch("8");
    ASN1ObjectIdentifier id_aes192_ECB = aes.branch("21");
    ASN1ObjectIdentifier id_aes192_CBC = aes.branch("22");
    ASN1ObjectIdentifier id_aes192_OFB = aes.branch("23");
    ASN1ObjectIdentifier id_aes192_CFB = aes.branch("24");
    ASN1ObjectIdentifier id_aes192_wrap = aes.branch("25");
    ASN1ObjectIdentifier id_aes192_GCM = aes.branch("26");
    ASN1ObjectIdentifier id_aes192_CCM = aes.branch("27");
    ASN1ObjectIdentifier id_aes192_wrap_pad = aes.branch("28");
    ASN1ObjectIdentifier id_aes256_ECB = aes.branch("41");
    ASN1ObjectIdentifier id_aes256_CBC = aes.branch("42");
    ASN1ObjectIdentifier id_aes256_OFB = aes.branch("43");
    ASN1ObjectIdentifier id_aes256_CFB = aes.branch("44");
    ASN1ObjectIdentifier id_aes256_wrap = aes.branch("45");
    ASN1ObjectIdentifier id_aes256_GCM = aes.branch("46");
    ASN1ObjectIdentifier id_aes256_CCM = aes.branch("47");
    ASN1ObjectIdentifier id_aes256_wrap_pad = aes.branch("48");
    ASN1ObjectIdentifier sigAlgs = nistAlgorithm.branch("3");
    ASN1ObjectIdentifier id_dsa_with_sha2 = sigAlgs;
    ASN1ObjectIdentifier dsa_with_sha224 = sigAlgs.branch("1");
    ASN1ObjectIdentifier dsa_with_sha256 = sigAlgs.branch("2");
    ASN1ObjectIdentifier dsa_with_sha384 = sigAlgs.branch("3");
    ASN1ObjectIdentifier dsa_with_sha512 = sigAlgs.branch("4");
    ASN1ObjectIdentifier id_dsa_with_sha3_224 = sigAlgs.branch("5");
    ASN1ObjectIdentifier id_dsa_with_sha3_256 = sigAlgs.branch("6");
    ASN1ObjectIdentifier id_dsa_with_sha3_384 = sigAlgs.branch("7");
    ASN1ObjectIdentifier id_dsa_with_sha3_512 = sigAlgs.branch("8");
    ASN1ObjectIdentifier id_ecdsa_with_sha3_224 = sigAlgs.branch("9");
    ASN1ObjectIdentifier id_ecdsa_with_sha3_256 = sigAlgs.branch("10");
    ASN1ObjectIdentifier id_ecdsa_with_sha3_384 = sigAlgs.branch("11");
    ASN1ObjectIdentifier id_ecdsa_with_sha3_512 = sigAlgs.branch("12");
    ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_224 = sigAlgs.branch("13");
    ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_256 = sigAlgs.branch("14");
    ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_384 = sigAlgs.branch("15");
    ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_512 = sigAlgs.branch("16");
}

【问题讨论】:

  • 定义'不起作用'。
  • @EJP 密码不允许我进入
  • 我不知道为什么 isValidMac 会失败,对我来说它因 BC 版本(仅 1.53 到 1.56)而异,但如果你真的想要 openssl pkcs12 -export -des3 的等价物,那应该是 keybag=pbeWithSHAAnd3_KeyTripleDES_CBC (不是 pbes2 /sha1,AES256) certbag=pbeWithSHAAnd40BitRC2_CBC (not 128) 和 p12pbmac/sha1 (not SHA256), itercount 2048 而不是 1024,并且随着这些算法的变化(但不打扰 itercount),它在 BC 和 openssl 中始终适用于我(我无法测试钥匙串)。
  • @dave_thompson_085 我应该为 Java 1.7 使用不同版本的 BC 吗?
  • @dave_thompson_085 你能解释一下我需要更换哪个 SHA256 吗?我没有看到任何 p12pbmac/sha1 选项作为 NISTObjectIdentifiers 的一部分。 pbeWithSHAAnd3_KeyTripleDES_CBC 是有道理的。

标签: java bouncycastle


【解决方案1】:

Meta:这是一种解决方法,不是针对所提出的 Q 的答案,但需要格式化。

要以简单的方式创建 PKCS12,只需按照其 javadoc 中的说明使用 KeyStore,它应该在您的 IDE or on Oracle's website 中可用。这是一个结合 javadoc 片段的最小示例。由于您的 Q 没有显示您从哪里获得 createCredentials 数据 来自,因此对于这个示例,我只是从现有的 JKS 中读取;根据需要更改此设置。并使用更好的密码!

我演示了使用默认提供程序 (SunJSSE) 和 BC 提供程序。我在最终测试中发现的一个警告:BC 需要在 Oracle java 上安装“无限强度策略”——至少到 j8;据报道,这个“功能”终于在 j9 中被删除了,但我还没有测试过。也许它将 168 的 TDES 密钥大小视为超过 128,即使 TDES strength 仅为 112 并且应该被允许。

char[] pw = "password".toCharArray(); // dummy for test
boolean useBC = System.getProperty("useBC")!=null;
KeyStore jks = KeyStore.getInstance("JKS");
InputStream f1 = new FileInputStream ("old.jks"); jks.load(f1, pw); f1.close();
PrivateKey pkey = (PrivateKey)jks.getKey("mykey", pw);
Certificate[] chain = jks.getCertificateChain("mykey");

// only needed once, and not at all if pre-configured in java.security  
if(useBC) Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

// then do something like this
KeyStore p12 = useBC? KeyStore.getInstance("PKCS12","BC"): KeyStore.getInstance("PKCS12");
p12.load(null); p12.setKeyEntry("mykey", pkey, pw, chain);
OutputStream f2 = new FileOutputStream ("new.p12"); p12.store(f2,pw); f2.close();

【讨论】:

    猜你喜欢
    • 2019-12-07
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    相关资源
    最近更新 更多