2011-02-26 30 views
10

Quiero generar un formato PKCS8 PrivateKey cifrado con contraseña, y trato con este código:¿Cómo generar un KeyPair de RSA con una clave privada encriptada con contraseña?

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

Pero yo no sé cómo cifrar una contraseña con 3DES para que sea compatible con el formato OpenSSL.

Respuesta

28

Sé que es un poco tarde pero también he estado buscando una manera de hacer esto y mientras buscaba encontré su pregunta, ahora que he encontrado una manera de hacerlo, decidí volver y compartir esto:

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

este código de ejemplo se basa en el código folowing que encontré: http://www.jensign.com/JavaScience/PEM/EncPrivKeyInfo/EncPrivKeyInfo.java

pero el recurso folowing también me ayudó a entender un poco mejor: http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html

+7

'aleatoria al azar = new Random(); 'debe ser' SecureRandom r andom = new SecureRandom(); ' – Carsten

+0

Gracias por su sugerencia Carsten! – Hrzio

+1

A partir de JDK 8, uno debe usar 'SecureRandom random = SecureRandom.getInstanceStrong();' para asegurarse de que está utilizando una implementación sólida como sugiere esta documentación de Oracle: https://docs.oracle.com/javase/tutorial /security/apisign/step2.html – CrashproofCode

Cuestiones relacionadas