import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.spec.*; import java.security.cert.*; import java.security.interfaces.*; import javax.crypto.*; import javax.crypto.spec.*; // Based on sample at: // http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html // Requires J2SE 1.5 due to bugs in earlier versions in algorithm parameters // Reads an encoded pkcs#8 PrivateKeyInfo file, encrypts it using PBE, wraps in // an EncryptedPrivateKeyInfo, writes to file; decrypts the EncryptedPrivateKeyInfo // blob and displays private key parameters of original RSA private key. // See also: // http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/EncryptedPrivateKeyInfo.html // http://java.sun.com/j2se/1.5.0/docs/api/java/security/spec/PKCS8EncodedKeySpec.html // http://www.openssl.org/docs/apps/pkcs8.html // // Copyright M. Gallant 04/07/2005 class EncPrivKeyInfo { public static void main(String[] args) { if (args.length != 1) System.out.println("Usage: EncPrivKeyInfo "); else try { PBEKeySpec pbeKeySpec; PBEParameterSpec pbeParamSpec; SecretKeyFactory keyFac; byte[] encodedprivkey = getFileBytes(args[0]) ; byte[] salt = { (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c, (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 }; String MYPBEALG = "PBEWithSHA1AndDESede" ; //String MYPBEALG = "PBEWithMD5AndDES" ; // Iteration count int count = 20; // Create PBE parameter set pbeParamSpec = new PBEParameterSpec(salt, count); // Prompt user for encryption password. // Collect user password as char array (using the // "readPasswd" method from above), and convert // it into a SecretKey object, using a PBE key // factory. // System.out.print("Enter encryption password: "); // System.out.flush(); String password = "This is a stupid password!" ; pbeKeySpec = new PBEKeySpec(password.toCharArray()); 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); // displayData(ciphertext); //----- Now construct PKCS #8 EncryptedPrivateKeyInfo object ----------- AlgorithmParameters algparms = AlgorithmParameters.getInstance(MYPBEALG); algparms.init(pbeParamSpec) ; EncryptedPrivateKeyInfo encinfo = new EncryptedPrivateKeyInfo(algparms, ciphertext) ; FileOutputStream sigfos = new FileOutputStream("encrypedprivkey8"); //write PKCS#8 EncryptedPrivateKeyInfo to file sigfos.write(encinfo.getEncoded()); sigfos.close(); // ------- now recover the private key and display information -------------- PKCS8EncodedKeySpec pvkKeySpec = encinfo.getKeySpec(pbeKey) ; System.out.println("\nGot the PKCS8EncodedKeySpec .. \n") ; KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPrivateKey mypvkKey = (RSAPrivateKey)keyFactory.generatePrivate(pvkKeySpec); System.out.println(mypvkKey.toString()) ; } catch(Exception ioe) { System.out.println(ioe.toString()); } } private static void displayData(byte[] data) { int bytecon = 0; //to get unsigned byte representation for(int i=1; i<=data.length ; i++){ bytecon = data[i-1] & 0xFF ; // byte-wise AND converts signed byte to unsigned. if(bytecon<16) System.out.print("0" + Integer.toHexString(bytecon).toUpperCase() + " "); // pad on left if single hex digit. else System.out.print(Integer.toHexString(bytecon).toUpperCase() + " "); // pad on left if single hex digit. if(i%16==0) System.out.println(); } } private static byte[] getFileBytes(String infile){ File f = new File(infile) ; int sizecontent = ((int) f.length()); byte[] data = new byte[sizecontent]; try { FileInputStream freader = new FileInputStream(f); freader.read(data, 0, sizecontent) ; freader.close(); return data; } catch(IOException ioe) { System.out.println(ioe.toString()); return null; } } }