5

I have tried answers of these questions:

Bouncy Castle : PEMReader => PEMParser

Read an encrypted private key with bouncycastle/spongycastle

However as my encrypted key is encoded in DER when I call

Object object = pemParser.readObject(); 

object is null.

I can convert it to PEM with this openssl's command (it decrypts the key too)

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

but I need to read the key in its original file

2 Answers 2

9

Both those Qs are about parsing, and decrypting, files using OpenSSL's 'legacy PEM' encryption. You are using PKCS8 encryption which is different though similar, so Reading PKCS8 in PEM format: Cannot find provider is closer. You can use most of the approach there, but skipping the PEM parse:

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()); 
Sign up to request clarification or add additional context in comments.

3 Comments

if I follow this approach I encounter this error: org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.13 not available: SecretKeyFactory PBKDF2withHMACSHA256 implementation not found any idea how to do?
@tonidi: make sure you are using bcprov 1.55 or higher, and it is in your provider list (or use one of the setProvider methods on the DecryptorBuilder). SunJCE in j8 up also supports this SKF, but I wouldn't try that unless necessary since bcpkix has other dependencies on bcprov.
I resolved this using SpongyCastle as provider but now I encounter this new error caused by decryptPrivateKeyInfo: org.spongycastle.pkcs.PKCSException: unable to read encrypted data: Error while finalizing cipher (opened a new question: stackoverflow.com/questions/50911431/…)
0

By using SpongyCastle we can get good results. I made some code that will get the desired result. SpongyCastle Jars can be downloaded from below:- core, prov, pkix

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(); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.