| 395 | } |
| 396 | |
| 397 | static void generate_hsm(const char *hsm_secret_path) |
| 398 | { |
| 399 | const char *mnemonic, *passphrase; |
| 400 | enum hsm_secret_error error; |
| 401 | |
| 402 | /* Get mnemonic from user using consistent interface */ |
| 403 | mnemonic = read_stdin_mnemonic(tmpctx, &error); |
| 404 | if (!mnemonic) |
| 405 | errx(EXITCODE_ERROR_HSM_FILE, "Could not read mnemonic: %s", hsm_secret_error_str(error)); |
| 406 | |
| 407 | /* Get optional passphrase */ |
| 408 | printf("Warning: remember that different passphrases yield different " |
| 409 | "bitcoin wallets.\n"); |
| 410 | printf("If left empty, no password is used (echo is disabled).\n"); |
| 411 | printf("Enter your passphrase: \n"); |
| 412 | fflush(stdout); |
| 413 | passphrase = read_stdin_pass(tmpctx, &error); |
| 414 | if (!passphrase) |
| 415 | errx(EXITCODE_ERROR_HSM_FILE, "Could not read passphrase: %s", hsm_secret_error_str(error)); |
| 416 | if (streq(passphrase, "")) { |
| 417 | passphrase = NULL; |
| 418 | } |
| 419 | |
| 420 | /* Write to file using your new mnemonic format */ |
| 421 | int fd = open(hsm_secret_path, O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 422 | if (fd < 0) { |
| 423 | err(ERROR_USAGE, "Unable to create hsm_secret file"); |
| 424 | } |
| 425 | |
| 426 | /* Hash the derived seed for validation */ |
| 427 | struct sha256 seed_hash; |
| 428 | if (!derive_seed_hash(mnemonic, passphrase, &seed_hash)) |
| 429 | errx(ERROR_USAGE, "Error deriving seed from mnemonic"); |
| 430 | |
| 431 | /* Write seed hash (32 bytes) + mnemonic */ |
| 432 | if (!write_all(fd, &seed_hash, sizeof(seed_hash))) |
| 433 | err(ERROR_USAGE, "Error writing seed hash to hsm_secret file"); |
| 434 | |
| 435 | /* Write the mnemonic */ |
| 436 | if (!write_all(fd, mnemonic, strlen(mnemonic))) |
| 437 | err(ERROR_USAGE, "Error writing mnemonic to hsm_secret file"); |
| 438 | |
| 439 | if (fsync(fd) != 0) |
| 440 | err(ERROR_USAGE, "Error fsyncing hsm_secret file"); |
| 441 | |
| 442 | if (close(fd) != 0) |
| 443 | err(ERROR_USAGE, "Error closing hsm_secret file"); |
| 444 | |
| 445 | printf("New hsm_secret file created at %s\n", hsm_secret_path); |
| 446 | printf("Format: %s\n", passphrase ? "mnemonic with passphrase" : "mnemonic without passphrase"); |
| 447 | if (passphrase) { |
| 448 | printf("Remember your passphrase - it's required to use this hsm_secret!\n"); |
| 449 | } |
| 450 | |
| 451 | /* passphrase and mnemonic will be automatically cleaned up by tmpctx */ |
| 452 | } |
| 453 | |
| 454 | static void derive_to_remote(const struct unilateral_close_info *info, const char *hsm_secret_path) |
no test coverage detected