001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.j2ssh.transport.publickey;
027:
028: import com.sshtools.j2ssh.SshThread;
029:
030: import java.io.BufferedReader;
031: import java.io.File;
032: import java.io.FileOutputStream;
033: import java.io.IOException;
034: import java.io.InputStreamReader;
035:
036: import java.lang.reflect.Method;
037:
038: /*import java.util.logging.FileHandler;
039: import java.util.logging.Handler;
040: import java.util.logging.Level;
041: import java.util.logging.Logger;
042: import java.util.logging.SimpleFormatter;*/
043: public class SshKeyGenerator {
044: private static String filename = null;
045: private static String type = "dsa";
046: private static int bits = 1024;
047: private static boolean useGUI;
048: private static boolean guiAvailable;
049: private static boolean toOpenSSH = false;
050: private static boolean toSECSH = false;
051: private static boolean changePass = false;
052:
053: // Test if the GUI is available
054: static {
055: try {
056: Class.forName("com.sshtools.j2ssh.keygen.Main");
057: guiAvailable = true;
058: } catch (ClassNotFoundException cnfe) {
059: }
060: }
061:
062: /**
063: * Creates a new SshKeyGenerator object.
064: */
065: public SshKeyGenerator() {
066: }
067:
068: /**
069: *
070: *
071: * @param type
072: * @param bits
073: * @param filename
074: * @param username
075: * @param passphrase
076: *
077: * @throws IOException
078: */
079: public void generateKeyPair(String type, int bits, String filename,
080: String username, String passphrase) throws IOException {
081: System.out
082: .println("****Sshtools.com SSH Key Pair Generator****");
083:
084: String keyType = type;
085:
086: if (keyType.equalsIgnoreCase("DSA")) {
087: keyType = "ssh-dss";
088: }
089:
090: if (keyType.equalsIgnoreCase("RSA")) {
091: keyType = "ssh-rsa";
092: }
093:
094: final SshKeyPair pair = SshKeyPairFactory.newInstance(keyType);
095: System.out.println("Generating " + String.valueOf(bits)
096: + " bit " + keyType + " key pair");
097:
098: Thread thread = new SshThread(new Runnable() {
099: public void run() {
100: pair.generate(SshKeyGenerator.this .bits);
101: }
102: }, "Key generator", true);
103: thread.start();
104:
105: while (thread.isAlive()) {
106: System.out.print(".");
107:
108: try {
109: Thread.sleep(100);
110: } catch (InterruptedException e) {
111: }
112: }
113:
114: System.out.println();
115: System.out.println("Creating Public Key file " + filename
116: + ".pub");
117:
118: // Now save the files
119: SshPublicKeyFile pub = SshPublicKeyFile.create(pair
120: .getPublicKey(), new SECSHPublicKeyFormat(username,
121: String.valueOf(bits) + "-bit " + type));
122: FileOutputStream out = new FileOutputStream(filename + ".pub");
123: out.write(pub.getBytes());
124: out.close();
125: System.out.println("Generating Private Key file " + filename);
126:
127: if (passphrase == null) {
128: passphrase = promptForPassphrase(true);
129: }
130:
131: SshPrivateKeyFile prv = SshPrivateKeyFile.create(pair
132: .getPrivateKey(), passphrase,
133: new SshtoolsPrivateKeyFormat(username, String
134: .valueOf(bits)
135: + "-bit " + type));
136: out = new FileOutputStream(filename);
137: out.write(prv.getBytes());
138: out.close();
139: }
140:
141: /**
142: *
143: *
144: * @param args
145: */
146: public static void main(String[] args) {
147: try {
148: processCommandLine(args);
149:
150: // Setup a logfile
151:
152: /*Handler fh = new FileHandler("ssh-keygen.log");
153: fh.setFormatter(new SimpleFormatter());
154: Logger.getLogger("com.sshtools").setUseParentHandlers(false);
155: Logger.getLogger("com.sshtools").addHandler(fh);
156: Logger.getLogger("com.sshtools").setLevel(Level.ALL);*/
157: if (useGUI) {
158: Class c = Class
159: .forName("com.sshtools.j2ssh.keygen.Main");
160: Method m = c.getMethod("main", new Class[] { args
161: .getClass() });
162: m.invoke(null, new Object[] { new String[] {} });
163: } else {
164: File f = new File(filename);
165:
166: if (filename == null) {
167: System.err
168: .print("You must supply a valid file to convert!");
169: System.exit(1);
170: }
171:
172: if (toOpenSSH || toSECSH) {
173: if (!f.exists()) {
174: System.err.print("The file "
175: + f.getAbsolutePath()
176: + " does not exist!");
177: System.exit(1);
178: }
179:
180: try {
181: if (toOpenSSH) {
182: System.out.print(convertPublicKeyFile(f,
183: new OpenSSHPublicKeyFormat()));
184: } else {
185: System.out.print(convertPublicKeyFile(f,
186: new SECSHPublicKeyFormat()));
187: }
188: } catch (InvalidSshKeyException e) {
189: System.err
190: .println("The key format is invalid!");
191: } catch (IOException ioe) {
192: System.err
193: .println("An error occurs whilst reading the file "
194: + f.getAbsolutePath());
195: }
196:
197: System.exit(0);
198: }
199:
200: if (changePass) {
201: if (!f.exists()) {
202: System.err.print("The file "
203: + f.getAbsolutePath()
204: + " does not exist!");
205: System.exit(1);
206: }
207:
208: changePassphrase(f);
209: } else {
210: SshKeyGenerator generator = new SshKeyGenerator();
211: String username = System.getProperty("user.name");
212: generator.generateKeyPair(type, bits, filename,
213: username, null);
214: }
215: }
216: } catch (Throwable t) {
217: t.printStackTrace();
218: }
219: }
220:
221: /**
222: *
223: *
224: * @param args
225: */
226: public static void processCommandLine(String[] args) {
227: if (args.length > 0) {
228: for (int i = 0; i < args.length; i++) {
229: if (args[i].equalsIgnoreCase("-b")) {
230: bits = Integer.parseInt(args[++i]);
231: } else if (args[i].equalsIgnoreCase("-t")) {
232: type = args[++i];
233: } else if (args[i].equalsIgnoreCase("-p")) {
234: changePass = true;
235: } else if (args[i].equalsIgnoreCase("-g")
236: && guiAvailable) {
237: useGUI = true;
238: } else if (args[i].equalsIgnoreCase("-i")) {
239: toOpenSSH = true;
240: } else if (args[i].equalsIgnoreCase("-e")) {
241: toSECSH = true;
242: } else if (!args[i].startsWith("-")) {
243: if (filename != null) {
244: printUsage();
245: System.exit(1);
246: }
247:
248: filename = args[i];
249: }
250: }
251: }
252:
253: if (!useGUI && (filename == null)) {
254: printUsage();
255: System.exit(0);
256: }
257: }
258:
259: private static void changePassphrase(File f) {
260: System.out.println("Opening Private Key file "
261: + f.getAbsolutePath());
262:
263: try {
264: System.out.println("Opening Private Key file "
265: + f.getAbsolutePath());
266:
267: String oldPassphrase = promptForPassphrase(false);
268: String newPassphrase = promptForPassphrase(true);
269: changePassphrase(f, oldPassphrase, newPassphrase);
270: } catch (InvalidSshKeyException e) {
271: System.err.println("The key format is invalid!");
272: } catch (IOException ioe) {
273: System.err
274: .println("An error occurs whilst reading the file "
275: + f.getAbsolutePath());
276: }
277: }
278:
279: /**
280: *
281: *
282: * @param f
283: * @param oldPassphrase
284: * @param newPassphrase
285: *
286: * @throws IOException
287: * @throws InvalidSshKeyException
288: */
289: public static void changePassphrase(File f, String oldPassphrase,
290: String newPassphrase) throws IOException,
291: InvalidSshKeyException {
292: // Open up the file with its current format
293: SshPrivateKeyFile file = SshPrivateKeyFile.parse(f);
294: System.out
295: .println("Saving Private Key file with new passphrase");
296: file.changePassphrase(oldPassphrase, newPassphrase);
297:
298: FileOutputStream out = null;
299:
300: try {
301: out = new FileOutputStream(f);
302: out.write(file.getBytes());
303: } finally {
304: if (out != null) {
305: out.close();
306: }
307: }
308: }
309:
310: /**
311: *
312: *
313: * @param f
314: * @param convert
315: *
316: * @return
317: *
318: * @throws InvalidSshKeyException
319: * @throws IOException
320: */
321: public static String convertPublicKeyFile(File f,
322: SshPublicKeyFormat convert) throws InvalidSshKeyException,
323: IOException {
324: // Open up the file with its current format
325: SshPublicKeyFile file = SshPublicKeyFile.parse(f);
326:
327: // Set the new format
328: file.setFormat(convert);
329:
330: // Output to stdout
331: return file.toString();
332: }
333:
334: private static void printUsage() {
335: System.out.println("Usage: SshKeyGenerator [options] filename");
336: System.out.println("Options:");
337: System.out
338: .println("-b bits Number of bits in the key to create.");
339: System.out
340: .println("-e Convert OpenSSH to IETF SECSH key file.");
341: System.out
342: .println("-i Convert IETF SECSH to OpenSSH key file.");
343: System.out.println("-t type The type of key to create.");
344: System.out
345: .println("-p Change the passphrase of the private key file.");
346:
347: if (guiAvailable) {
348: System.out.println("-g \t\tUse GUI to create key");
349: }
350: }
351:
352: private static String promptForPassphrase(boolean confirm)
353: throws IOException {
354: // Confirm the passphrase
355: BufferedReader reader = new BufferedReader(
356: new InputStreamReader(System.in));
357: String pass1 = "";
358: String pass2 = "";
359:
360: while (true) {
361: System.out.print("Enter passphrase: ");
362: pass1 = reader.readLine();
363:
364: if (!confirm) {
365: break;
366: }
367:
368: System.out.print("Confirm passphrase: ");
369: pass2 = reader.readLine();
370:
371: if (pass1.equals(pass2)) {
372: if (pass1.trim().length() == 0) {
373: System.out
374: .print("You supplied an empty passphrase, are you sure? [Yes|No]: ");
375: pass2 = reader.readLine();
376:
377: if (pass2.equalsIgnoreCase("YES")) {
378: break;
379: }
380: } else {
381: break;
382: }
383: } else {
384: System.out
385: .println("The passphrases supplied were not indentical! Try again");
386: }
387: }
388:
389: return pass1;
390: }
391: }
|