2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * Created: Mon Mar 27 02:26:40 1995 ylo
6 * Identity and host key generation and maintenance.
15 #include "fingerprint.h"
17 /* Generated private key. */
20 /* Generated public key. */
23 /* Number of bits in the RSA key. This value can be changed on the command line. */
27 * Flag indicating that we just want to change the passphrase. This can be
28 * set on the command line.
30 int change_passphrase = 0;
33 * Flag indicating that we just want to change the comment. This can be set
34 * on the command line.
36 int change_comment = 0;
40 /* Flag indicating that we just want to see the key fingerprint */
41 int print_fingerprint = 0;
43 /* The identity file name, given on the command line or entered by the user. */
44 char identity_file[1024];
45 int have_identity = 0;
47 /* This is set to the passphrase if given on the command line. */
48 char *identity_passphrase = NULL;
50 /* This is set to the new passphrase if given on the command line. */
51 char *identity_new_passphrase = NULL;
53 /* This is set to the new comment if given on the command line. */
54 char *identity_comment = NULL;
57 #ifdef HAVE___PROGNAME
58 extern char *__progname;
59 #else /* HAVE___PROGNAME */
60 const char *__progname = "ssh-keygen";
61 #endif /* HAVE___PROGNAME */
64 ask_filename(struct passwd *pw, const char *prompt)
67 snprintf(identity_file, sizeof(identity_file), "%s/%s",
68 pw->pw_dir, SSH_CLIENT_IDENTITY);
69 printf("%s (%s): ", prompt, identity_file);
71 if (fgets(buf, sizeof(buf), stdin) == NULL)
73 if (strchr(buf, '\n'))
74 *strchr(buf, '\n') = 0;
75 if (strcmp(buf, "") != 0)
76 strlcpy(identity_file, buf, sizeof(identity_file));
81 do_fingerprint(struct passwd *pw)
88 ask_filename(pw, "Enter file in which the key is");
89 if (stat(identity_file, &st) < 0) {
90 perror(identity_file);
93 public_key = RSA_new();
94 if (!load_public_key(identity_file, public_key, &comment)) {
97 int dummy, invalid = 0;
98 FILE *f = fopen(identity_file, "r");
101 if (f && fgets(line, sizeof(line), f)) {
103 line[strlen(line) - 1] = '\0';
104 if (auth_rsa_read_key(&cp, &dummy, e, n)) {
107 comment = xstrdup(cp ? cp : "no comment");
115 printf("%s is not a valid key file.\n", identity_file);
121 printf("%d %s %s\n", BN_num_bits(public_key->n),
122 fingerprint(public_key->e, public_key->n),
124 RSA_free(public_key);
129 * Perform changing a passphrase. The argument is the passwd structure
130 * for the current user.
133 do_change_passphrase(struct passwd *pw)
136 char *old_passphrase, *passphrase1, *passphrase2;
141 ask_filename(pw, "Enter file in which the key is");
142 if (stat(identity_file, &st) < 0) {
143 perror(identity_file);
146 public_key = RSA_new();
147 if (!load_public_key(identity_file, public_key, NULL)) {
148 printf("%s is not a valid key file.\n", identity_file);
151 /* Clear the public key since we are just about to load the whole file. */
152 RSA_free(public_key);
154 /* Try to load the file with empty passphrase. */
155 private_key = RSA_new();
156 if (!load_private_key(identity_file, "", private_key, &comment)) {
157 if (identity_passphrase)
158 old_passphrase = xstrdup(identity_passphrase);
160 old_passphrase = read_passphrase("Enter old passphrase: ", 1);
161 if (!load_private_key(identity_file, old_passphrase, private_key, &comment)) {
162 memset(old_passphrase, 0, strlen(old_passphrase));
163 xfree(old_passphrase);
164 printf("Bad passphrase.\n");
167 memset(old_passphrase, 0, strlen(old_passphrase));
168 xfree(old_passphrase);
170 printf("Key has comment '%s'\n", comment);
172 /* Ask the new passphrase (twice). */
173 if (identity_new_passphrase) {
174 passphrase1 = xstrdup(identity_new_passphrase);
178 read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
179 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
181 /* Verify that they are the same. */
182 if (strcmp(passphrase1, passphrase2) != 0) {
183 memset(passphrase1, 0, strlen(passphrase1));
184 memset(passphrase2, 0, strlen(passphrase2));
187 printf("Pass phrases do not match. Try again.\n");
190 /* Destroy the other copy. */
191 memset(passphrase2, 0, strlen(passphrase2));
195 /* Save the file using the new passphrase. */
196 if (!save_private_key(identity_file, passphrase1, private_key, comment)) {
197 printf("Saving the key failed: %s: %s.\n",
198 identity_file, strerror(errno));
199 memset(passphrase1, 0, strlen(passphrase1));
201 RSA_free(private_key);
205 /* Destroy the passphrase and the copy of the key in memory. */
206 memset(passphrase1, 0, strlen(passphrase1));
208 RSA_free(private_key); /* Destroys contents */
211 printf("Your identification has been saved with the new passphrase.\n");
216 * Change the comment of a private key file.
219 do_change_comment(struct passwd *pw)
221 char new_comment[1024], *comment;
229 ask_filename(pw, "Enter file in which the key is");
230 if (stat(identity_file, &st) < 0) {
231 perror(identity_file);
235 * Try to load the public key from the file the verify that it is
236 * readable and of the proper format.
238 public_key = RSA_new();
239 if (!load_public_key(identity_file, public_key, NULL)) {
240 printf("%s is not a valid key file.\n", identity_file);
243 private_key = RSA_new();
245 if (load_private_key(identity_file, "", private_key, &comment))
246 passphrase = xstrdup("");
248 if (identity_passphrase)
249 passphrase = xstrdup(identity_passphrase);
250 else if (identity_new_passphrase)
251 passphrase = xstrdup(identity_new_passphrase);
253 passphrase = read_passphrase("Enter passphrase: ", 1);
254 /* Try to load using the passphrase. */
255 if (!load_private_key(identity_file, passphrase, private_key, &comment)) {
256 memset(passphrase, 0, strlen(passphrase));
258 printf("Bad passphrase.\n");
262 printf("Key now has comment '%s'\n", comment);
264 if (identity_comment) {
265 strlcpy(new_comment, identity_comment, sizeof(new_comment));
267 printf("Enter new comment: ");
269 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
270 memset(passphrase, 0, strlen(passphrase));
271 RSA_free(private_key);
274 if (strchr(new_comment, '\n'))
275 *strchr(new_comment, '\n') = 0;
278 /* Save the file using the new passphrase. */
279 if (!save_private_key(identity_file, passphrase, private_key, new_comment)) {
280 printf("Saving the key failed: %s: %s.\n",
281 identity_file, strerror(errno));
282 memset(passphrase, 0, strlen(passphrase));
284 RSA_free(private_key);
288 memset(passphrase, 0, strlen(passphrase));
290 RSA_free(private_key);
292 strlcat(identity_file, ".pub", sizeof(identity_file));
293 f = fopen(identity_file, "w");
295 printf("Could not save your public key in %s\n", identity_file);
298 fprintf(f, "%d ", BN_num_bits(public_key->n));
299 tmpbuf = BN_bn2dec(public_key->e);
300 fprintf(f, "%s ", tmpbuf);
302 tmpbuf = BN_bn2dec(public_key->n);
303 fprintf(f, "%s %s\n", tmpbuf, new_comment);
309 printf("The comment in your key file has been changed.\n");
316 printf("ssh-keygen version %s\n", SSH_VERSION);
317 printf("Usage: %s [-b bits] [-p] [-c] [-f file] [-P pass] [-N new-pass] [-C comment]\n", __progname);
322 * Main program for key management.
325 main(int ac, char **av)
327 char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
333 char hostname[MAXHOSTNAMELEN];
337 /* check if RSA support exists */
338 if (rsa_alive() == 0) {
340 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
344 /* we need this for the home * directory. */
345 pw = getpwuid(getuid());
347 printf("You don't exist, go away!\n");
351 while ((opt = getopt(ac, av, "qpclb:f:P:N:C:")) != EOF) {
355 if (bits < 512 || bits > 32768) {
356 printf("Bits has bad value.\n");
362 print_fingerprint = 1;
366 change_passphrase = 1;
374 strlcpy(identity_file, optarg, sizeof(identity_file));
379 identity_passphrase = optarg;
383 identity_new_passphrase = optarg;
387 identity_comment = optarg;
400 printf("Too many arguments.\n");
403 if (change_passphrase && change_comment) {
404 printf("Can only have one of -p and -c.\n");
407 if (print_fingerprint)
409 if (change_passphrase)
410 do_change_passphrase(pw);
412 do_change_comment(pw);
419 /* Generate the rsa key pair. */
420 private_key = RSA_new();
421 public_key = RSA_new();
422 rsa_generate_key(private_key, public_key, bits);
425 ask_filename(pw, "Enter file in which to save the key");
427 /* Create ~/.ssh directory if it doesn\'t already exist. */
428 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, SSH_USER_DIR);
429 if (strstr(identity_file, dotsshdir) != NULL &&
430 stat(dotsshdir, &st) < 0) {
431 if (mkdir(dotsshdir, 0755) < 0)
432 error("Could not create directory '%s'.", dotsshdir);
434 printf("Created directory '%s'.\n", dotsshdir);
436 /* If the file already exists, ask the user to confirm. */
437 if (stat(identity_file, &st) >= 0) {
439 printf("%s already exists.\n", identity_file);
440 printf("Overwrite (y/n)? ");
442 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
444 if (yesno[0] != 'y' && yesno[0] != 'Y')
447 /* Ask for a passphrase (twice). */
448 if (identity_passphrase)
449 passphrase1 = xstrdup(identity_passphrase);
450 else if (identity_new_passphrase)
451 passphrase1 = xstrdup(identity_new_passphrase);
455 read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
456 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
457 if (strcmp(passphrase1, passphrase2) != 0) {
458 /* The passphrases do not match. Clear them and retry. */
459 memset(passphrase1, 0, strlen(passphrase1));
460 memset(passphrase2, 0, strlen(passphrase2));
463 printf("Passphrases do not match. Try again.\n");
464 goto passphrase_again;
466 /* Clear the other copy of the passphrase. */
467 memset(passphrase2, 0, strlen(passphrase2));
471 if (identity_comment) {
472 strlcpy(comment, identity_comment, sizeof(comment));
474 /* Create default commend field for the passphrase. */
475 if (gethostname(hostname, sizeof(hostname)) < 0) {
476 perror("gethostname");
479 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
482 /* Save the key with the given passphrase and comment. */
483 if (!save_private_key(identity_file, passphrase1, private_key, comment)) {
484 printf("Saving the key failed: %s: %s.\n",
485 identity_file, strerror(errno));
486 memset(passphrase1, 0, strlen(passphrase1));
490 /* Clear the passphrase. */
491 memset(passphrase1, 0, strlen(passphrase1));
494 /* Clear the private key and the random number generator. */
495 RSA_free(private_key);
499 printf("Your identification has been saved in %s.\n", identity_file);
501 strlcat(identity_file, ".pub", sizeof(identity_file));
502 f = fopen(identity_file, "w");
504 printf("Could not save your public key in %s\n", identity_file);
507 fprintf(f, "%d ", BN_num_bits(public_key->n));
508 tmpbuf = BN_bn2dec(public_key->e);
509 fprintf(f, "%s ", tmpbuf);
511 tmpbuf = BN_bn2dec(public_key->n);
512 fprintf(f, "%s %s\n", tmpbuf, comment);
517 printf("Your public key has been saved in %s.\n", identity_file);
518 printf("The key fingerprint is:\n");
519 printf("%d %s %s\n", BN_num_bits(public_key->n),
520 fingerprint(public_key->e, public_key->n),