]>
Commit | Line | Data |
---|---|---|
8efc0c15 | 1 | /* |
2 | ||
3 | ssh-keygen.c | |
4 | ||
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> | |
6 | ||
7 | Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | |
8 | All rights reserved | |
9 | ||
10 | Created: Mon Mar 27 02:26:40 1995 ylo | |
11 | ||
12 | Identity and host key generation and maintenance. | |
13 | ||
14 | */ | |
15 | ||
16 | #include "includes.h" | |
17 | RCSID("$Id$"); | |
18 | ||
19 | #include "rsa.h" | |
20 | #include "ssh.h" | |
21 | #include "xmalloc.h" | |
f095fcc7 | 22 | #include "fingerprint.h" |
8efc0c15 | 23 | |
f601d847 | 24 | #ifdef HAVE___PROGNAME |
25 | extern char *__progname; | |
26 | #else /* HAVE___PROGNAME */ | |
27 | const char *__progname = "ssh-keygen"; | |
28 | #endif /* HAVE___PROGNAME */ | |
29 | ||
8efc0c15 | 30 | /* Generated private key. */ |
31 | RSA *private_key; | |
32 | ||
33 | /* Generated public key. */ | |
34 | RSA *public_key; | |
35 | ||
36 | /* Number of bits in the RSA key. This value can be changed on the command | |
37 | line. */ | |
38 | int bits = 1024; | |
39 | ||
40 | /* Flag indicating that we just want to change the passphrase. This can be | |
41 | set on the command line. */ | |
42 | int change_passphrase = 0; | |
43 | ||
44 | /* Flag indicating that we just want to change the comment. This can be set | |
45 | on the command line. */ | |
46 | int change_comment = 0; | |
47 | ||
48 | int quiet = 0; | |
49 | ||
f095fcc7 | 50 | /* Flag indicating that we just want to see the key fingerprint */ |
51 | int print_fingerprint = 0; | |
52 | ||
5ad13cd7 | 53 | /* The identity file name, given on the command line or entered by the user. */ |
54 | char identity_file[1024]; | |
55 | int have_identity = 0; | |
8efc0c15 | 56 | |
57 | /* This is set to the passphrase if given on the command line. */ | |
58 | char *identity_passphrase = NULL; | |
59 | ||
60 | /* This is set to the new passphrase if given on the command line. */ | |
61 | char *identity_new_passphrase = NULL; | |
62 | ||
63 | /* This is set to the new comment if given on the command line. */ | |
64 | char *identity_comment = NULL; | |
65 | ||
5ad13cd7 | 66 | /* argv0 */ |
67 | extern char *__progname; | |
8efc0c15 | 68 | |
5ad13cd7 | 69 | void |
70 | ask_filename(struct passwd *pw, const char *prompt) | |
8efc0c15 | 71 | { |
5ad13cd7 | 72 | char buf[1024]; |
73 | snprintf(identity_file, sizeof(identity_file), "%s/%s", | |
74 | pw->pw_dir, SSH_CLIENT_IDENTITY); | |
75 | printf("%s (%s): ", prompt, identity_file); | |
76 | fflush(stdout); | |
77 | if (fgets(buf, sizeof(buf), stdin) == NULL) | |
78 | exit(1); | |
79 | if (strchr(buf, '\n')) | |
80 | *strchr(buf, '\n') = 0; | |
81 | if (strcmp(buf, "") != 0) | |
82 | strlcpy(identity_file, buf, sizeof(identity_file)); | |
83 | have_identity = 1; | |
f095fcc7 | 84 | } |
8efc0c15 | 85 | |
f095fcc7 | 86 | void |
87 | do_fingerprint(struct passwd *pw) | |
88 | { | |
5ad13cd7 | 89 | char *comment; |
f095fcc7 | 90 | RSA *public_key; |
91 | struct stat st; | |
92 | ||
5ad13cd7 | 93 | if (!have_identity) |
94 | ask_filename(pw, "Enter file in which the key is"); | |
95 | if (stat(identity_file, &st) < 0) | |
f095fcc7 | 96 | { |
5ad13cd7 | 97 | perror(identity_file); |
f095fcc7 | 98 | exit(1); |
99 | } | |
100 | public_key = RSA_new(); | |
5ad13cd7 | 101 | if (!load_public_key(identity_file, public_key, &comment)) { |
f095fcc7 | 102 | char *cp, line[1024]; |
103 | BIGNUM *e, *n; | |
104 | int dummy, invalid = 0; | |
5ad13cd7 | 105 | FILE *f = fopen(identity_file, "r"); |
f095fcc7 | 106 | n = BN_new(); |
107 | e = BN_new(); | |
108 | if (f && fgets(line, sizeof(line), f)) { | |
109 | cp = line; | |
110 | line[strlen(line)-1] = '\0'; | |
111 | if (auth_rsa_read_key(&cp, &dummy, e, n)) { | |
112 | public_key->e = e; | |
113 | public_key->n = n; | |
114 | comment = xstrdup(cp ? cp : "no comment"); | |
115 | } else { | |
116 | invalid = 1; | |
117 | } | |
118 | } else { | |
119 | invalid = 1; | |
120 | } | |
121 | if (invalid) { | |
5ad13cd7 | 122 | printf("%s is not a valid key file.\n", identity_file); |
f095fcc7 | 123 | BN_free(e); |
124 | BN_free(n); | |
125 | exit(1); | |
126 | } | |
127 | } | |
128 | ||
129 | printf("%d %s %s\n", BN_num_bits(public_key->n), | |
130 | fingerprint(public_key->e, public_key->n), | |
131 | comment); | |
132 | RSA_free(public_key); | |
133 | exit(0); | |
134 | } | |
135 | ||
5ad13cd7 | 136 | /* Perform changing a passphrase. The argument is the passwd structure |
137 | for the current user. */ | |
f095fcc7 | 138 | |
139 | void | |
140 | do_change_passphrase(struct passwd *pw) | |
141 | { | |
5ad13cd7 | 142 | char *comment; |
f095fcc7 | 143 | char *old_passphrase, *passphrase1, *passphrase2; |
144 | struct stat st; | |
145 | RSA *private_key; | |
146 | ||
5ad13cd7 | 147 | if (!have_identity) |
148 | ask_filename(pw, "Enter file in which the key is"); | |
8efc0c15 | 149 | /* Check if the file exists. */ |
5ad13cd7 | 150 | if (stat(identity_file, &st) < 0) |
8efc0c15 | 151 | { |
5ad13cd7 | 152 | perror(identity_file); |
8efc0c15 | 153 | exit(1); |
154 | } | |
155 | ||
156 | /* Try to load the public key from the file the verify that it is | |
157 | readable and of the proper format. */ | |
158 | public_key = RSA_new(); | |
5ad13cd7 | 159 | if (!load_public_key(identity_file, public_key, NULL)) |
8efc0c15 | 160 | { |
5ad13cd7 | 161 | printf("%s is not a valid key file.\n", identity_file); |
8efc0c15 | 162 | exit(1); |
163 | } | |
164 | /* Clear the public key since we are just about to load the whole file. */ | |
165 | RSA_free(public_key); | |
166 | ||
167 | /* Try to load the file with empty passphrase. */ | |
168 | private_key = RSA_new(); | |
5ad13cd7 | 169 | if (!load_private_key(identity_file, "", private_key, &comment)) { |
8efc0c15 | 170 | /* Read passphrase from the user. */ |
171 | if (identity_passphrase) | |
172 | old_passphrase = xstrdup(identity_passphrase); | |
173 | else | |
174 | old_passphrase = read_passphrase("Enter old passphrase: ", 1); | |
175 | /* Try to load using the passphrase. */ | |
5ad13cd7 | 176 | if (!load_private_key(identity_file, old_passphrase, private_key, &comment)) |
8efc0c15 | 177 | { |
178 | memset(old_passphrase, 0, strlen(old_passphrase)); | |
179 | xfree(old_passphrase); | |
180 | printf("Bad passphrase.\n"); | |
181 | exit(1); | |
182 | } | |
183 | /* Destroy the passphrase. */ | |
184 | memset(old_passphrase, 0, strlen(old_passphrase)); | |
185 | xfree(old_passphrase); | |
186 | } | |
187 | printf("Key has comment '%s'\n", comment); | |
6fa724bc | 188 | |
8efc0c15 | 189 | /* Ask the new passphrase (twice). */ |
190 | if (identity_new_passphrase) | |
191 | { | |
192 | passphrase1 = xstrdup(identity_new_passphrase); | |
193 | passphrase2 = NULL; | |
194 | } | |
195 | else | |
196 | { | |
197 | passphrase1 = | |
198 | read_passphrase("Enter new passphrase (empty for no passphrase): ", 1); | |
199 | passphrase2 = read_passphrase("Enter same passphrase again: ", 1); | |
200 | ||
201 | /* Verify that they are the same. */ | |
202 | if (strcmp(passphrase1, passphrase2) != 0) | |
203 | { | |
204 | memset(passphrase1, 0, strlen(passphrase1)); | |
205 | memset(passphrase2, 0, strlen(passphrase2)); | |
206 | xfree(passphrase1); | |
207 | xfree(passphrase2); | |
208 | printf("Pass phrases do not match. Try again.\n"); | |
209 | exit(1); | |
210 | } | |
211 | /* Destroy the other copy. */ | |
212 | memset(passphrase2, 0, strlen(passphrase2)); | |
213 | xfree(passphrase2); | |
214 | } | |
215 | ||
216 | /* Save the file using the new passphrase. */ | |
5ad13cd7 | 217 | if (!save_private_key(identity_file, passphrase1, private_key, comment)) |
8efc0c15 | 218 | { |
219 | printf("Saving the key failed: %s: %s.\n", | |
5ad13cd7 | 220 | identity_file, strerror(errno)); |
8efc0c15 | 221 | memset(passphrase1, 0, strlen(passphrase1)); |
222 | xfree(passphrase1); | |
223 | RSA_free(private_key); | |
224 | xfree(comment); | |
225 | exit(1); | |
226 | } | |
227 | /* Destroy the passphrase and the copy of the key in memory. */ | |
228 | memset(passphrase1, 0, strlen(passphrase1)); | |
229 | xfree(passphrase1); | |
230 | RSA_free(private_key); /* Destroys contents */ | |
231 | xfree(comment); | |
232 | ||
233 | printf("Your identification has been saved with the new passphrase.\n"); | |
234 | exit(0); | |
235 | } | |
236 | ||
237 | /* Change the comment of a private key file. */ | |
238 | ||
239 | void | |
240 | do_change_comment(struct passwd *pw) | |
241 | { | |
5ad13cd7 | 242 | char new_comment[1024], *comment; |
8efc0c15 | 243 | RSA *private_key; |
244 | char *passphrase; | |
245 | struct stat st; | |
246 | FILE *f; | |
247 | char *tmpbuf; | |
248 | ||
5ad13cd7 | 249 | if (!have_identity) |
250 | ask_filename(pw, "Enter file in which the key is"); | |
8efc0c15 | 251 | /* Check if the file exists. */ |
5ad13cd7 | 252 | if (stat(identity_file, &st) < 0) |
8efc0c15 | 253 | { |
5ad13cd7 | 254 | perror(identity_file); |
8efc0c15 | 255 | exit(1); |
256 | } | |
257 | ||
258 | /* Try to load the public key from the file the verify that it is | |
259 | readable and of the proper format. */ | |
260 | public_key = RSA_new(); | |
5ad13cd7 | 261 | if (!load_public_key(identity_file, public_key, NULL)) |
8efc0c15 | 262 | { |
5ad13cd7 | 263 | printf("%s is not a valid key file.\n", identity_file); |
8efc0c15 | 264 | exit(1); |
265 | } | |
266 | ||
267 | private_key = RSA_new(); | |
268 | /* Try to load the file with empty passphrase. */ | |
5ad13cd7 | 269 | if (load_private_key(identity_file, "", private_key, &comment)) |
8efc0c15 | 270 | passphrase = xstrdup(""); |
271 | else | |
272 | { | |
273 | /* Read passphrase from the user. */ | |
274 | if (identity_passphrase) | |
275 | passphrase = xstrdup(identity_passphrase); | |
276 | else | |
277 | if (identity_new_passphrase) | |
278 | passphrase = xstrdup(identity_new_passphrase); | |
279 | else | |
280 | passphrase = read_passphrase("Enter passphrase: ", 1); | |
281 | /* Try to load using the passphrase. */ | |
5ad13cd7 | 282 | if (!load_private_key(identity_file, passphrase, private_key, &comment)) |
8efc0c15 | 283 | { |
284 | memset(passphrase, 0, strlen(passphrase)); | |
285 | xfree(passphrase); | |
286 | printf("Bad passphrase.\n"); | |
287 | exit(1); | |
288 | } | |
289 | } | |
290 | printf("Key now has comment '%s'\n", comment); | |
291 | ||
292 | if (identity_comment) | |
293 | { | |
f095fcc7 | 294 | strlcpy(new_comment, identity_comment, sizeof(new_comment)); |
8efc0c15 | 295 | } |
296 | else | |
297 | { | |
298 | printf("Enter new comment: "); | |
299 | fflush(stdout); | |
300 | if (!fgets(new_comment, sizeof(new_comment), stdin)) | |
301 | { | |
302 | memset(passphrase, 0, strlen(passphrase)); | |
303 | RSA_free(private_key); | |
304 | exit(1); | |
305 | } | |
306 | ||
307 | /* Remove terminating newline from comment. */ | |
308 | if (strchr(new_comment, '\n')) | |
309 | *strchr(new_comment, '\n') = 0; | |
310 | } | |
311 | ||
312 | /* Save the file using the new passphrase. */ | |
5ad13cd7 | 313 | if (!save_private_key(identity_file, passphrase, private_key, new_comment)) |
8efc0c15 | 314 | { |
315 | printf("Saving the key failed: %s: %s.\n", | |
5ad13cd7 | 316 | identity_file, strerror(errno)); |
8efc0c15 | 317 | memset(passphrase, 0, strlen(passphrase)); |
318 | xfree(passphrase); | |
319 | RSA_free(private_key); | |
320 | xfree(comment); | |
321 | exit(1); | |
322 | } | |
323 | ||
324 | /* Destroy the passphrase and the private key in memory. */ | |
325 | memset(passphrase, 0, strlen(passphrase)); | |
326 | xfree(passphrase); | |
327 | RSA_free(private_key); | |
328 | ||
329 | /* Save the public key in text format in a file with the same name but | |
330 | .pub appended. */ | |
5ad13cd7 | 331 | strlcat(identity_file, ".pub", sizeof(identity_file)); |
332 | f = fopen(identity_file, "w"); | |
8efc0c15 | 333 | if (!f) |
334 | { | |
5ad13cd7 | 335 | printf("Could not save your public key in %s\n", identity_file); |
8efc0c15 | 336 | exit(1); |
337 | } | |
338 | fprintf(f, "%d ", BN_num_bits(public_key->n)); | |
339 | tmpbuf = BN_bn2dec(public_key->e); | |
340 | fprintf(f, "%s ", tmpbuf); | |
341 | free (tmpbuf); | |
342 | tmpbuf = BN_bn2dec(public_key->n); | |
343 | fprintf(f, "%s %s\n", tmpbuf, new_comment); | |
344 | free (tmpbuf); | |
345 | fclose(f); | |
346 | ||
347 | xfree(comment); | |
348 | ||
349 | printf("The comment in your key file has been changed.\n"); | |
350 | exit(0); | |
351 | } | |
352 | ||
5ad13cd7 | 353 | void |
354 | usage(void) | |
355 | { | |
356 | printf("ssh-keygen version %s\n", SSH_VERSION); | |
357 | printf("Usage: %s [-b bits] [-p] [-c] [-f file] [-P pass] [-N new-pass] [-C comment]\n", __progname); | |
358 | exit(1); | |
359 | } | |
360 | ||
8efc0c15 | 361 | /* Main program for key management. */ |
362 | ||
363 | int | |
364 | main(int ac, char **av) | |
365 | { | |
2f2cc3f9 | 366 | char dotsshdir[16*1024], comment[1024], *passphrase1, *passphrase2; |
8efc0c15 | 367 | struct passwd *pw; |
5ad13cd7 | 368 | char *tmpbuf; |
8efc0c15 | 369 | int opt; |
370 | struct stat st; | |
371 | FILE *f; | |
372 | char hostname[MAXHOSTNAMELEN]; | |
373 | extern int optind; | |
374 | extern char *optarg; | |
375 | ||
376 | /* check if RSA support exists */ | |
377 | if (rsa_alive() == 0) { | |
f095fcc7 | 378 | extern char *__progname; |
8efc0c15 | 379 | |
380 | fprintf(stderr, | |
381 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", | |
382 | __progname); | |
383 | exit(1); | |
384 | } | |
385 | ||
386 | /* Get user\'s passwd structure. We need this for the home directory. */ | |
387 | pw = getpwuid(getuid()); | |
388 | if (!pw) | |
389 | { | |
390 | printf("You don't exist, go away!\n"); | |
391 | exit(1); | |
392 | } | |
393 | ||
8efc0c15 | 394 | /* Parse command line arguments. */ |
f095fcc7 | 395 | while ((opt = getopt(ac, av, "qpclb:f:P:N:C:")) != EOF) |
8efc0c15 | 396 | { |
397 | switch (opt) | |
398 | { | |
399 | case 'b': | |
400 | bits = atoi(optarg); | |
401 | if (bits < 512 || bits > 32768) | |
402 | { | |
403 | printf("Bits has bad value.\n"); | |
404 | exit(1); | |
405 | } | |
406 | break; | |
407 | ||
f095fcc7 | 408 | case 'l': |
409 | print_fingerprint = 1; | |
410 | break; | |
411 | ||
8efc0c15 | 412 | case 'p': |
413 | change_passphrase = 1; | |
414 | break; | |
415 | ||
416 | case 'c': | |
417 | change_comment = 1; | |
418 | break; | |
419 | ||
420 | case 'f': | |
5ad13cd7 | 421 | strlcpy(identity_file, optarg, sizeof(identity_file)); |
422 | have_identity = 1; | |
8efc0c15 | 423 | break; |
424 | ||
425 | case 'P': | |
426 | identity_passphrase = optarg; | |
427 | break; | |
428 | ||
429 | case 'N': | |
430 | identity_new_passphrase = optarg; | |
431 | break; | |
432 | ||
433 | case 'C': | |
434 | identity_comment = optarg; | |
435 | break; | |
436 | ||
437 | case 'q': | |
438 | quiet = 1; | |
439 | break; | |
440 | ||
441 | case '?': | |
442 | default: | |
5ad13cd7 | 443 | usage(); |
8efc0c15 | 444 | } |
445 | } | |
446 | if (optind < ac) | |
447 | { | |
448 | printf("Too many arguments.\n"); | |
5ad13cd7 | 449 | usage(); |
8efc0c15 | 450 | } |
451 | if (change_passphrase && change_comment) | |
452 | { | |
453 | printf("Can only have one of -p and -c.\n"); | |
5ad13cd7 | 454 | usage(); |
8efc0c15 | 455 | } |
456 | ||
f095fcc7 | 457 | if (print_fingerprint) |
458 | do_fingerprint(pw); | |
459 | ||
8efc0c15 | 460 | /* If the user requested to change the passphrase, do it now. This |
461 | function never returns. */ | |
462 | if (change_passphrase) | |
463 | do_change_passphrase(pw); | |
464 | ||
465 | /* If the user requested to change the comment, do it now. This function | |
466 | never returns. */ | |
467 | if (change_comment) | |
468 | do_change_comment(pw); | |
469 | ||
470 | arc4random_stir(); | |
471 | ||
472 | if (quiet) | |
473 | rsa_set_verbose(0); | |
474 | ||
475 | /* Generate the rsa key pair. */ | |
476 | private_key = RSA_new(); | |
477 | public_key = RSA_new(); | |
478 | rsa_generate_key(private_key, public_key, bits); | |
479 | ||
5ad13cd7 | 480 | if (!have_identity) |
481 | ask_filename(pw, "Enter file in which to save the key"); | |
8efc0c15 | 482 | |
2f2cc3f9 | 483 | /* Create ~/.ssh directory if it doesn\'t already exist. */ |
484 | snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, SSH_USER_DIR); | |
485 | if (strstr(identity_file, dotsshdir) != NULL && | |
486 | stat(dotsshdir, &st) < 0) { | |
487 | if (mkdir(dotsshdir, 0755) < 0) | |
488 | error("Could not create directory '%s'.", dotsshdir); | |
489 | else if(!quiet) | |
490 | printf("Created directory '%s'.\n", dotsshdir); | |
491 | } | |
492 | ||
493 | /* If the file already exists, ask the user to confirm. */ | |
5ad13cd7 | 494 | if (stat(identity_file, &st) >= 0) |
8efc0c15 | 495 | { |
2f2cc3f9 | 496 | char yesno[3]; |
5ad13cd7 | 497 | printf("%s already exists.\n", identity_file); |
8efc0c15 | 498 | printf("Overwrite (y/n)? "); |
499 | fflush(stdout); | |
2f2cc3f9 | 500 | if (fgets(yesno, sizeof(yesno), stdin) == NULL) |
8efc0c15 | 501 | exit(1); |
2f2cc3f9 | 502 | if (yesno[0] != 'y' && yesno[0] != 'Y') |
8efc0c15 | 503 | exit(1); |
504 | } | |
505 | ||
506 | /* Ask for a passphrase (twice). */ | |
507 | if (identity_passphrase) | |
508 | passphrase1 = xstrdup(identity_passphrase); | |
509 | else | |
510 | if (identity_new_passphrase) | |
511 | passphrase1 = xstrdup(identity_new_passphrase); | |
512 | else | |
513 | { | |
514 | passphrase_again: | |
515 | passphrase1 = | |
516 | read_passphrase("Enter passphrase (empty for no passphrase): ", 1); | |
517 | passphrase2 = read_passphrase("Enter same passphrase again: ", 1); | |
518 | if (strcmp(passphrase1, passphrase2) != 0) | |
519 | { | |
520 | /* The passphrases do not match. Clear them and retry. */ | |
521 | memset(passphrase1, 0, strlen(passphrase1)); | |
522 | memset(passphrase2, 0, strlen(passphrase2)); | |
523 | xfree(passphrase1); | |
524 | xfree(passphrase2); | |
525 | printf("Passphrases do not match. Try again.\n"); | |
526 | goto passphrase_again; | |
527 | } | |
528 | /* Clear the other copy of the passphrase. */ | |
529 | memset(passphrase2, 0, strlen(passphrase2)); | |
530 | xfree(passphrase2); | |
531 | } | |
532 | ||
533 | /* Create default commend field for the passphrase. The user can later | |
534 | edit this field. */ | |
535 | if (identity_comment) | |
536 | { | |
2f2cc3f9 | 537 | strlcpy(comment, identity_comment, sizeof(comment)); |
8efc0c15 | 538 | } |
539 | else | |
540 | { | |
541 | if (gethostname(hostname, sizeof(hostname)) < 0) | |
542 | { | |
543 | perror("gethostname"); | |
544 | exit(1); | |
545 | } | |
2f2cc3f9 | 546 | snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); |
8efc0c15 | 547 | } |
548 | ||
549 | /* Save the key with the given passphrase and comment. */ | |
2f2cc3f9 | 550 | if (!save_private_key(identity_file, passphrase1, private_key, comment)) |
8efc0c15 | 551 | { |
552 | printf("Saving the key failed: %s: %s.\n", | |
5ad13cd7 | 553 | identity_file, strerror(errno)); |
8efc0c15 | 554 | memset(passphrase1, 0, strlen(passphrase1)); |
555 | xfree(passphrase1); | |
5ad13cd7 | 556 | exit(1); |
8efc0c15 | 557 | } |
558 | /* Clear the passphrase. */ | |
559 | memset(passphrase1, 0, strlen(passphrase1)); | |
560 | xfree(passphrase1); | |
561 | ||
562 | /* Clear the private key and the random number generator. */ | |
563 | RSA_free(private_key); | |
564 | arc4random_stir(); | |
565 | ||
566 | if (!quiet) | |
5ad13cd7 | 567 | printf("Your identification has been saved in %s.\n", identity_file); |
8efc0c15 | 568 | |
8efc0c15 | 569 | /* Save the public key in text format in a file with the same name but |
570 | .pub appended. */ | |
5ad13cd7 | 571 | strlcat(identity_file, ".pub", sizeof(identity_file)); |
572 | f = fopen(identity_file, "w"); | |
8efc0c15 | 573 | if (!f) |
574 | { | |
5ad13cd7 | 575 | printf("Could not save your public key in %s\n", identity_file); |
8efc0c15 | 576 | exit(1); |
577 | } | |
578 | fprintf(f, "%d ", BN_num_bits(public_key->n)); | |
579 | tmpbuf = BN_bn2dec(public_key->e); | |
580 | fprintf(f, "%s ", tmpbuf); | |
581 | free(tmpbuf); | |
582 | tmpbuf = BN_bn2dec(public_key->n); | |
2f2cc3f9 | 583 | fprintf(f, "%s %s\n", tmpbuf, comment); |
8efc0c15 | 584 | free(tmpbuf); |
585 | fclose(f); | |
586 | ||
2f2cc3f9 | 587 | if (!quiet) { |
588 | printf("Your public key has been saved in %s.\n", identity_file); | |
589 | printf("The key fingerprint is:\n"); | |
590 | printf("%d %s %s\n", BN_num_bits(public_key->n), | |
591 | fingerprint(public_key->e, public_key->n), | |
592 | comment); | |
593 | } | |
8efc0c15 | 594 | |
595 | exit(0); | |
596 | } |