有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用privatekey encryption PBEWIHMACSHA512andaes128创建PKCS12密钥库

我需要在Scala/Java中构建一个PKCS-12文件,我希望使用基于AES的私钥加密(例如PBewithhmacsha512andaes128)

我使用此代码(取自here

val outputStream = new FileOutputStream(file)
val salt = new Array[Byte](20)
new SecureRandom().nextBytes(salt)
val kspkcs12 = KeyStore.getInstance("PKCS12")
kspkcs12.load(null, null)
kspkcs12.setEntry("test", new KeyStore.PrivateKeyEntry(keys.getPrivate, Array(cert)),
  new KeyStore.PasswordProtection("changeMe".toCharArray, "PBEWithHmacSHA512AndAES_128", new PBEParameterSpec(salt,
    100000)))
kspkcs12.store(outputStream, "changeMe".toArray)

现在,当使用

 openssl pkcs12 -info -in filename.p12  -noout

我得到:

MAC:sha1 Iteration 100000 PKCS7 Data Shrouded Keybag: PBES2<unsupported parameters> PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 50000 Certificate bag'

为什么我得到的是“PKCS7加密数据”而不是PKCS12? 我从报纸上了解到

"PBES2<unsupported parameters>"

提供程序不支持请求的算法的消息。是否有PKCS12提供程序可以这样做


共 (1) 个答案

  1. # 1 楼答案

    Why am I getting a "PKCS7 Encrypted data" instead of PKCS12?

    PKCS是一堆规范,即每个更高级别的规范重复使用较低级别的规范

    在PKCS#12的情况下,我们至少会遇到:

    • PKCS#12(密钥库格式)
    • PKCS#7(签名/加密邮件)
    • PKCS#5(PBKDF2)
    • PKCS#9(信息摘要)
    • PKCS#8(密钥对格式)

    因此,在输出中看到与PKCS#7相关的消息是正常的

    I understand from the "PBES2<unsupported parameters>" that the provider does not support the requested algorithm.

    是的,这是Java中的一个bug。内置JCE提供程序在输出流中错误地对PBES2标记进行了两次编码:

    偶尔

    public void derEncode (OutputStream out) throws IOException {
        DerOutputStream bytes = new DerOutputStream();
        DerOutputStream tmp = new DerOutputStream();
    
        bytes.putOID(algid);                               // <<< Writes 1.2.840.113549.1.5.13
    

    每隔一段时间:

    protected byte[] engineGetEncoded() throws IOException {
        DerOutputStream out = new DerOutputStream();
        DerOutputStream pBES2Algorithms = new DerOutputStream();
        pBES2Algorithms.putOID(pkcs5PBES2_OID);            // <<< Writes 1.2.840.113549.1.5.13 again
    

    以下是它产生的结果(我将HMAC SHA256与AES256结合使用):

    $ openssl asn1parse -inform der -strparse 973 < test.p12
        0:d=0  hl=4 l=1441 cons: SEQUENCE          
        4:d=1  hl=4 l=1437 cons: SEQUENCE          
        8:d=2  hl=2 l=  11 prim: OBJECT            :pkcs8ShroudedKeyBag
       21:d=2  hl=4 l=1358 cons: cont [ 0 ]        
       25:d=3  hl=4 l=1354 cons: SEQUENCE          
       29:d=4  hl=2 l= 116 cons: SEQUENCE          
       31:d=5  hl=2 l=   9 prim: OBJECT            :PBES2
       42:d=5  hl=2 l= 103 cons: SEQUENCE          
       44:d=6  hl=2 l=   9 prim: OBJECT            :PBES2   <<<<< PBES2 tag encoded twice!!
       55:d=6  hl=2 l=  90 cons: SEQUENCE          
       57:d=7  hl=2 l=  57 cons: SEQUENCE          
       59:d=8  hl=2 l=   9 prim: OBJECT            :PBKDF2
       70:d=8  hl=2 l=  44 cons: SEQUENCE          
       72:d=9  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:9F642532C15BBF1E566AA6429DA450EFBF0FF265
       94:d=9  hl=2 l=   3 prim: INTEGER           :0186A0
       99:d=9  hl=2 l=   1 prim: INTEGER           :20
      102:d=9  hl=2 l=  12 cons: SEQUENCE          
      104:d=10 hl=2 l=   8 prim: OBJECT            :hmacWithSHA256
      114:d=10 hl=2 l=   0 prim: NULL              
      116:d=7  hl=2 l=  29 cons: SEQUENCE          
      118:d=8  hl=2 l=   9 prim: OBJECT            :aes-256-cbc
      129:d=8  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:DF2D490C6BA58A19EDAF8D22E2A2CFA0
      147:d=4  hl=4 l=1232 prim: OCTET STRING      [HEX DUMP]:22343E6418F8C60857D9A5CC089D...
    

    下面是它应该是怎样的(来自openssl pkcs12 -encode的输出):

    $ openssl asn1parse -inform der -strparse 1003 < test.p12
        0:d=0  hl=4 l=1414 cons: SEQUENCE          
        4:d=1  hl=4 l=1410 cons: SEQUENCE          
        8:d=2  hl=2 l=  11 prim: OBJECT            :pkcs8ShroudedKeyBag
       21:d=2  hl=4 l=1329 cons: cont [ 0 ]        
       25:d=3  hl=4 l=1325 cons: SEQUENCE          
       29:d=4  hl=2 l=  87 cons: SEQUENCE          
       31:d=5  hl=2 l=   9 prim: OBJECT            :PBES2
       42:d=5  hl=2 l=  74 cons: SEQUENCE          
       44:d=6  hl=2 l=  41 cons: SEQUENCE          
       46:d=7  hl=2 l=   9 prim: OBJECT            :PBKDF2
       57:d=7  hl=2 l=  28 cons: SEQUENCE          
       59:d=8  hl=2 l=   8 prim: OCTET STRING      [HEX DUMP]:6FA108004C54EAC4
       69:d=8  hl=2 l=   2 prim: INTEGER           :0800
       73:d=8  hl=2 l=  12 cons: SEQUENCE          
       75:d=9  hl=2 l=   8 prim: OBJECT            :hmacWithSHA256
       85:d=9  hl=2 l=   0 prim: NULL              
       87:d=6  hl=2 l=  29 cons: SEQUENCE          
       89:d=7  hl=2 l=   9 prim: OBJECT            :aes-256-cbc
      100:d=7  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:CDACD92F68D13672599CD034CF3E791A
      118:d=4  hl=4 l=1232 prim: OCTET STRING      [HEX DUMP]:44725D0E70327934F75AD51CA7E3...
    

    它应该如何在RFC 2898, Appendix A.4中指定

    Is there a PKCS12 provider that does?

    是的,以下是如何使用BouncyCastle创建有效的PKCS#12密钥库:

    Security.addProvider(new BouncyCastleProvider());
    File file = new File("test.p12");
    char[] password = "test".toCharArray();
    
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(2048);
    KeyPair keypair = keyGen.genKeyPair();
    X500Name issuer = new X500Name("CN=test");
    X500Name subject = new X500Name("CN=test");
    BigInteger serial = new BigInteger("1");
    Date notBefore = new Date();
    Date notAfter = new Date(System.currentTimeMillis() + 365 * 24 * 3600000L);
    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(issuer, serial, notBefore, notAfter, subject, keypair.getPublic());
    ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").build(keypair.getPrivate());
    certBuilder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, new BasicConstraints(true));
    X509Certificate cert1 = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer));
    
    OutputEncryptor pkenc = new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC)
        .setPRF(PBKDF2Config.PRF_SHA256).setIterationCount(100000).setProvider("BC").build(password);
    
    JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
    PKCS12SafeBagBuilder certBagBuilder = new JcaPKCS12SafeBagBuilder(cert1);
    
    certBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("test"));
    SubjectKeyIdentifier pubKeyId = extUtils.createSubjectKeyIdentifier(cert1.getPublicKey());
    certBagBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute, pubKeyId);
    
    PKCS12SafeBagBuilder keyBagBuilder = new JcaPKCS12SafeBagBuilder(keypair.getPrivate(), pkenc);
    
    keyBagBuilder.addBagAttribute(PKCS12SafeBag.friendlyNameAttribute, new DERBMPString("test"));
    keyBagBuilder.addBagAttribute(PKCS12SafeBag.localKeyIdAttribute, pubKeyId);
    
    PKCS12PfxPduBuilder builder = new PKCS12PfxPduBuilder();
    
    builder.addData(keyBagBuilder.build());
    
    OutputEncryptor crtenc = new JcePKCSPBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC)
        .setIterationCount(50000).setProvider("BC").build(password);
    
    builder.addEncryptedData(crtenc, new PKCS12SafeBag[]{certBagBuilder.build()});
    
    PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(NISTObjectIdentifiers.id_sha256), password);
    
    try (FileOutputStream out = new FileOutputStream(file)) {
        out.write(pfx.getEncoded(ASN1Encoding.DL));
    }
    

    结果是:

    $ openssl pkcs12 -info -nodes -in test3.p12 -passin pass:test -noout
    MAC:sha256 Iteration 1024
    PKCS7 Data
    Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 100000, PRF hmacWithSHA256
    PKCS7 Encrypted data: pbeWithSHA1And128BitRC2-CBC, Iteration 50000
    Certificate bag