//============================================================================== // tribble/security/GenKeyPair.java //------------------------------------------------------------------------------ package tribble.security; // System imports import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.lang.Integer; import java.lang.String; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.text.SimpleDateFormat; import java.util.Date; import java.util.SimpleTimeZone; // Local imports // (None) /******************************************************************************* * Public/private key pair generator. * Generates a public/private key pair to be used for asymmetric (public key) * encryption. * *
* The public and private keys are written to text files formatted as XML.
* These key files can then be read by class {@link KeyReader}.
*
*
* @version $Revision: 1.6 $ $Date: 2003/08/09 17:24:32 $
* @since 2003-03-13
* @author
* David R. Tribble
* (david@tribble.com).
*
* Copyright ©2003 by David R. Tribble, all rights reserved.
*
* Permission is granted to freely use and distribute this source code
* provided that the original copyright and authorship notices remain
* intact.
*
* @see KeyReader
*/
public class GenKeyPair
{
// Identification
/** Source revision information. */
static final String REV =
"@(#)tribble/security/GenKeyPair.java $Revision: 1.6 $ $Date: 2003/08/09 17:24:32 $\n";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Public constants
/** Default key pair generation algorithm ("RSA"). */
public static final String DFL_ALGORITHM = "RSA";
/** Default key pair bit size (1024). */
public static final int DFL_KEYSIZE = 1024;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Public static methods
/***************************************************************************
* Generate a public/private encryption key pair.
*
*
* Usage * * java tribble.security.GenKeyPair * [-option...] public.xml private.xml * * *
* Options: *
*
* Writes the public half of the generated key pair to file * public.xml, and the private half to file * private.xml. * The output files are in stand-alone XML format. * * * @throws GeneralSecurityException * Thrown if a security exception occurs. * * @throws IOException * Thrown if and I/O (write) error occurs. * * @since 1.1, 2003-03-13 */ public static void main(String[] args) throws IOException, GeneralSecurityException { String algorithm = DFL_ALGORITHM; int keysize = DFL_KEYSIZE; Date now; SimpleDateFormat fmt; String pubFname; BufferedWriter pubFile; String priFname; BufferedWriter priFile; GenKeyPair kpGen; KeyPair kp; int i; // Get command options for (i = 0; i < args.length; i++) { if (args[i].charAt(0) != '-') break; if (args[i].equals("-a")) algorithm = args[++i]; else if (args[i].equals("-s")) keysize = Integer.parseInt(args[++i]); } // Check usage if (args.length < i+2) { System.out.println("Generate a public/private key pair."); System.out.println(); System.out.println("usage: java " + GenKeyPair.class.getName() + " [-option...] public.xml private.xml"); System.out.println(); System.out.println("Options:"); System.out.println(" -a alg Algorithm (default is " + DFL_ALGORITHM + ")."); System.out.println(" -s num Key size (default is " + DFL_KEYSIZE + ")."); System.exit(255); } // Open/write the public key output file pubFname = args[i++]; if (pubFname.equals("-")) { // Write to standard output pubFile = new BufferedWriter(new OutputStreamWriter(System.out)); } else { // Open/write the output file pubFile = new BufferedWriter(new FileWriter(pubFname)); } // Open/write the private key output file priFname = args[i++]; if (priFname.equals("-")) { // Write to standard output priFile = new BufferedWriter(new OutputStreamWriter(System.out)); } else { // Open/write the output file priFile = new BufferedWriter(new FileWriter(priFname)); } // Display the current date now = new Date(); fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); fmt.setTimeZone(new SimpleTimeZone(0, "Z")); System.out.println(fmt.format(now) + " Z"); // Generate the public/private key pair System.out.print("Generating a public/private key pair (" + algorithm + ", " + keysize + ")..."); System.out.flush(); kpGen = new GenKeyPair(algorithm, keysize); kp = kpGen.generate(); System.out.println(" done"); System.out.flush(); // Write the public key System.out.println(); System.out.println(pubFname); writeEncoded(kp.getPublic(), keysize, now, pubFile); // Write the private key System.out.println(); System.out.println(priFname); writeEncoded(kp.getPrivate(), keysize, now, priFile); // Clean up if (!pubFname.equals("-")) pubFile.close(); if (!priFname.equals("-")) priFile.close(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Private static methods /*************************************************************************** * Writes the public or private key to an output stream, formatted as XML. * *
* The XML output looks like: *
* <public-key or <private-key * created="2003-03-15 20:20:15 Z" * algorithm="RSA" * format="X.509" or format="PKCS#8" * protected="no" * encoding="base16" * size="1024"> * 308201B73082012C06072A8648CE3804013082011F02818100FD7F53811D7512 * 2952DF4A9C2EECE4E7F611B7523CEF4400C31E3F80B6512669455D402251FB59 * ...etc... * 13C1142A157B6177C9F5943CA2093903FF1AEC04B90CC670D2B738341C310FEC * 2618E3BA191F1884FEDD72C8B2C5191C34FBD45A5F5CADD6347018 * </public-key> or </private-key>* * * @param key * A public or private key. * * @param keysize * Size (in bits) of the public or private key. * * @param when * Date that the key was generated. * * @param out * An output stream. * * @throws IOException * Thrown if and I/O (write) error occurs. * * @since 1.6, 2003-08-09 (2003-03-14) * * @see #main */ private static void writeEncoded(Key key, int keysize, Date when, BufferedWriter out) throws IOException, GeneralSecurityException { String type; SimpleDateFormat fmt; byte[] enc; // Display key info enc = key.getEncoded(); type = (key instanceof PublicKey ? "public" : "private"); fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); fmt.setTimeZone(new SimpleTimeZone(0, "Z")); System.out.println(type + " key:"); System.out.println(" algorithm: " + key.getAlgorithm()); System.out.println(" format: " + key.getFormat()); System.out.println(" size: " + keysize); //out.write(""); //out.newLine(); out.write("<" + type + "-key"); out.newLine(); out.write(" created=\"" + fmt.format(when) + " Z\""); out.newLine(); out.write(" algorithm=\"" + key.getAlgorithm() + "\""); out.newLine(); out.write(" format=\"" + key.getFormat() + "\""); out.newLine(); out.write(" encoding=\"" + "base16" + "\""); out.newLine(); if (key instanceof PrivateKey) { out.write(" protected=\"no\""); out.newLine(); } out.write(" size=\"" + keysize + "\">"); out.newLine(); // Write the key as a hexadecimal string for (int i = 0; i < enc.length; i++) { int b; int d; if (i % 32 == 0 && i > 0) out.newLine(); // Write the next encoded byte as two hex digits b = enc[i] & 0xFF; d = b >> 4; d = (d > 9 ? d-0xA+'A' : d+'0'); out.write((char) d); d = b & 0x0F; d = (d > 9 ? d-0xA+'A' : d+'0'); out.write((char) d); } out.newLine(); // Finish out.write("" + type + "-key>"); out.newLine(); out.flush(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Private variables /** Key pair generator. */ private KeyPairGenerator m_gen; /** Random number generator. */ private SecureRandom m_rand; /** Public/private key pair. */ private KeyPair m_keys; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public constructors /*************************************************************************** * Default constructor. * * @throws NoSuchAlgorithmException * Thrown if the default generator algorithm is not available. * * @since 1.1, 2003-03-13 */ public GenKeyPair() throws GeneralSecurityException { // Create a key pair generator using a default algorithm this(DFL_ALGORITHM, DFL_KEYSIZE); } /*************************************************************************** * Constructor. * * @param algo * Name of the public/private key pair generation algorithm to use, e.g., * "DSA". * * @param size * Key size (in bits), e.g., 1024. * * @throws NoSuchAlgorithmException * Thrown if the specified generator algorithm is not available. * * @since 1.1, 2003-03-13 */ public GenKeyPair(String algo, int size) throws GeneralSecurityException { // Check args if (size % 8 != 0) throw new InvalidAlgorithmParameterException( "Key size is not a multiple of 8"); // Create a new key pair generator m_gen = KeyPairGenerator.getInstance(algo); // Initialize the generator m_rand = new SecureRandom(); m_gen.initialize(size, m_rand); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public methods /*************************************************************************** * Generate a public/private key pair. * * @return * A public/private key pair. * Note that the private key of the pair must be kept secret by the user of * the key pair. * * @since 1.1, 2003-03-13 */ public KeyPair generate() { // Generate a public/private key pair m_keys = m_gen.genKeyPair(); return (m_keys); } } // End GenKeyPair.java