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
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());
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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.