14

I want to generate a privatekey PKCS8 format encrypted with password, and I try with this code:

String password = "123456";
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
KeyPair key = gen.generateKeyPair();
PrivateKey privateKey = key.getPrivate();
PublicKey publicKey = key.getPublic();

FileOutputStream pvt = new FileOutputStream("d:\\pvt123456.der");
try {
    pvt.write(privateKey.getEncoded());
    pvt.flush();
} finally {
    pvt.close();
}
FileOutputStream pub = new FileOutputStream("d:\\pub123456.der");
try {
    pub.write(publicKey.getEncoded());
    pub.flush();
} finally {
    pub.close();
}

But I don´t know how to encrypt a password with 3des to be compatible with openssl format.

CSchulz
  • 10,882
  • 11
  • 60
  • 114
Ricardo Cunha
  • 2,013
  • 6
  • 24
  • 42

1 Answers1

34

I know it's a little bit late but I also have been looking for a way to do this and while i was searching I found your question, now that I have found a way to do this I decided to come back and share this:

// generate key pair

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();

// extract the encoded private key, this is an unencrypted PKCS#8 private key
byte[] encodedprivkey = keyPair.getPrivate().getEncoded();

// We must use a PasswordBasedEncryption algorithm in order to encrypt the private key, you may use any common algorithm supported by openssl, you can check them in the openssl documentation http://www.openssl.org/docs/apps/pkcs8.html
String MYPBEALG = "PBEWithSHA1AndDESede";
String password = "pleaseChangeit!";

int count = 20;// hash iteration count
SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
random.nextBytes(salt);

// Create PBE parameter set
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

Cipher pbeCipher = Cipher.getInstance(MYPBEALG);

// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

// Encrypt the encoded Private Key with the PBE key
byte[] ciphertext = pbeCipher.doFinal(encodedprivkey);

// Now construct  PKCS #8 EncryptedPrivateKeyInfo object
AlgorithmParameters algparms = AlgorithmParameters.getInstance(MYPBEALG);
algparms.init(pbeParamSpec);
EncryptedPrivateKeyInfo encinfo = new EncryptedPrivateKeyInfo(algparms, ciphertext);

// and here we have it! a DER encoded PKCS#8 encrypted key!
byte[] encryptedPkcs8 = encinfo.getEncoded();

This example code is based on the folowing code I found: http://www.jensign.com/JavaScience/PEM/EncPrivKeyInfo/EncPrivKeyInfo.java

but the folowing resource also helped me to understand a little bit better: http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html

Hrzio
  • 396
  • 3
  • 12
  • 8
    `Random random = new Random();` should be `SecureRandom random = new SecureRandom();` – Carsten Sep 26 '13 at 01:19
  • 1
    As of JDK 8, one should use `SecureRandom random = SecureRandom.getInstanceStrong();` to ensure that you're using strong implementation as suggested by this documentation from Oracle: https://docs.oracle.com/javase/tutorial/security/apisign/step2.html – hsson Aug 05 '15 at 20:06
  • Hei, I used your solution for encrypting and writing to disk the private key, but I am not able to read it and use it. When I'm trying to call `EncryptedPrivateKeyInfo(privateKeyBytesFromFile)` it throws an exception saying that it can not decode the data. – Dani Grosu Dec 21 '15 at 13:59
  • 1
    @CrashproofCode not really: http://www.2uo.de/myths-about-urandom/ - https://tersesystems.com/2015/12/17/the-right-way-to-use-securerandom/ – tObi Feb 20 '17 at 20:08
  • If you are generating key pair from password then using SecureRandom to generate salt makes no sense. Either salt should be input (like password) or fixed. Next time you run this function it will assign random salt and you will be unable to decrypt it. – asdjfiasd Sep 04 '18 at 13:03
  • what is the purpose of encrypting the private key ? – mjs Dec 06 '20 at 14:09