【问题标题】:How read a PKCS8 encrypted Private key which is also encoded in DER with bouncycastle?如何读取 PKCS8 加密私钥,该私钥也使用 bouncycastle 编码在 DER 中?
【发布时间】:2018-09-30 14:55:11
【问题描述】:

我已经尝试过这些问题的答案:

Bouncy Castle : PEMReader => PEMParser

Read an encrypted private key with bouncycastle/spongycastle

但是,当我调用时,我的加密密钥在 DER 中编码

Object object = pemParser.readObject(); 

对象为空。

我可以用这个 openssl 的命令把它转换成 PEM(它也解密密钥)

openssl pkcs8 -inform der -in pkey.key -out pkey.pem 

但我需要读取原始文件中的密钥

【问题讨论】:

    标签: java cryptography bouncycastle pem der


    【解决方案1】:

    这两个问题都是关于使用 OpenSSL 的“传统 PEM”加密来解析和解密文件。您使用的是不同但相似的 PKCS8 加密,因此 Reading PKCS8 in PEM format: Cannot find provider 更接近。您可以在那里使用大部分方法,但跳过 PEM 解析:

    import org.bouncycastle.asn1.ASN1Sequence;
    import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo; // NOT the 
    import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;       // javax ones!
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
    import org.bouncycastle.operator.InputDecryptorProvider;
    import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
    
        // args[0] = filename args[1] = password
        FileInputStream fis = new FileInputStream(args[0]);
        byte[] buff = new byte[9999]; int len = fis.read(buff); fis.close();
        // could use File.readAllBytes in j8 but my dev machine is old
    
        // create what PEMParser would have 
        ASN1Sequence derseq = ASN1Sequence.getInstance (Arrays.copyOf(buff,len));
        PKCS8EncryptedPrivateKeyInfo encobj = new PKCS8EncryptedPrivateKeyInfo(EncryptedPrivateKeyInfo.getInstance(derseq));
        // decrypt and convert key
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        InputDecryptorProvider decryptionProv = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(args[1].toCharArray());
        PrivateKeyInfo keyInfo = encobj.decryptPrivateKeyInfo(decryptionProv);
        PrivateKey key = converter.getPrivateKey(keyInfo);
    
        // now actually use key, this is just a dummy
        System.out.println (key.getAlgorithm());
    

    【讨论】:

    • 如果我遵循这种方法,我会遇到这个错误:org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.13 not available: SecretKeyFactory PBKDF2withHMACSHA256 implementation not found 任何想法怎么办?
    • @tonidi:确保您使用的是 bcprov 1.55 或更高版本,并且它在您的提供程序列表中(或使用DecryptorBuilder 上的setProvider 方法之一)。 j8 up 中的 SunJCE 也支持此 SKF,但除非必要,否则我不会尝试这样做,因为 bcpkix 对 bcprov 有其他依赖项。
    • 我使用 SpongyCastle 作为提供者解决了这个问题,但现在我遇到了由 decryptPrivateKeyInfo: org.spongycastle.pkcs.PKCSException: 无法读取加密数据引起的新错误:完成密码时出错(打开了一个新问题: stackoverflow.com/questions/50911431/…)
    【解决方案2】:

    通过使用 SpongyCastle,我们可以获得很好的效果。我编写了一些代码,可以得到想要的结果。 SpongyCastle 罐子可以从下面下载:- coreprovpkix

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.security.PrivateKey;
    import java.security.Provider;
    import java.security.Security;
    
    // need core.jar, prov.jar, bcpkix-jdk15on.jar
    import org.spongycastle.asn1.ASN1Sequence;
    import org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
    import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
    import org.spongycastle.openssl.jcajce.JcaPEMKeyConverter;
    import org.spongycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
    import org.spongycastle.operator.InputDecryptorProvider;
    import org.spongycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
    
    class Decrypt {
    
        private static void usage() {
            System.err.println(" Usage: encrypted.pk8 password out_decrypted.pk8");
            System.exit(2);
        }
    
        public static byte[] copyOf(byte[] original, int newLength) {
            byte[] copy = new byte[newLength];
            System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
            return copy;
        }
    
        public static void loadProvider(String providerClassName)
            throws ClassNotFoundException, IllegalAccessException, InstantiationException {
            Class providerClass = Class.forName(providerClassName);
            Provider provider = (Provider)providerClass.newInstance();
    //        Security.insertProviderAt(provider, 1);
            Security.addProvider(provider);
        }
    
        public static void main(String[] args) throws Exception {
            if (args.length != 3) usage();
    
            loadProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
    
            FileInputStream fis = new FileInputStream(args[0]);
            byte[] buff = new byte[fis.available()];
            int len = fis.read(buff);
            fis.close();
    
            // create what PEMParser would have
            ASN1Sequence derseq = ASN1Sequence.getInstance(copyOf(buff, len));
            EncryptedPrivateKeyInfo epkInfo = EncryptedPrivateKeyInfo.getInstance(derseq);
            PKCS8EncryptedPrivateKeyInfo encobj = new PKCS8EncryptedPrivateKeyInfo(epkInfo);
    
            // decrypt and convert key
            InputDecryptorProvider decryptionProv = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(args[1].toCharArray());
            PrivateKeyInfo keyInfo = encobj.decryptPrivateKeyInfo(decryptionProv);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("SC");
            PrivateKey key = converter.getPrivateKey(keyInfo);
    
            // now actually use key, this is just a dummy
            System.out.println(key.getAlgorithm());
    
            FileOutputStream fos = new FileOutputStream(args[2]);
            fos.write(key.getEncoded());
            fos.close();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-14
      • 2012-08-31
      • 2011-07-31
      • 2014-05-20
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多