@@ -43,7 +43,7 @@ static void show_usage(const char *progname)
4343 "<path/to/hsm_secret>\n" );
4444 printf (" - guesstoremote <P2WPKH address> <node id> <tries> "
4545 "<path/to/hsm_secret>\n" );
46- printf (" - generatehsm <path/to/new/hsm_secret>\n " );
46+ printf (" - generatehsm <path/to/new/hsm_secret> [<language_id> <word list> [<password>] " );
4747 printf (" - checkhsm <path/to/new/hsm_secret>\n" );
4848 printf (" - dumponchaindescriptors [--show-secrets] <path/to/hsm_secret> [network]\n" );
4949 printf (" - makerune <path/to/hsm_secret>\n" );
@@ -450,21 +450,31 @@ static int guess_to_remote(const char *address, struct node_id *node_id,
450450 return 1 ;
451451}
452452
453+ struct wordlist_lang {
454+ char * abbr ;
455+ char * name ;
456+ };
457+
458+ struct wordlist_lang languages [] = {
459+ {"en" , "English" },
460+ {"es" , "Spanish" },
461+ {"fr" , "French" },
462+ {"it" , "Italian" },
463+ {"jp" , "Japanese" },
464+ {"zhs" , "Chinese Simplified" },
465+ {"zht" , "Chinese Traditional" },
466+ };
467+
468+ static bool check_lang (const char * abbr )
469+ {
470+ for (size_t i = 0 ; i < ARRAY_SIZE (languages ); i ++ ) {
471+ if (streq (abbr , languages [i ].abbr ))
472+ return true;
473+ }
474+ return false;
475+ }
476+
453477static void get_words (struct words * * words ) {
454- struct wordlist_lang {
455- char * abbr ;
456- char * name ;
457- };
458-
459- struct wordlist_lang languages [] = {
460- {"en" , "English" },
461- {"es" , "Spanish" },
462- {"fr" , "French" },
463- {"it" , "Italian" },
464- {"jp" , "Japanese" },
465- {"zhs" , "Chinese Simplified" },
466- {"zht" , "Chinese Traditional" },
467- };
468478
469479 printf ("Select your language:\n" );
470480 for (size_t i = 0 ; i < ARRAY_SIZE (languages ); i ++ ) {
@@ -490,7 +500,7 @@ static void get_words(struct words **words) {
490500 bip39_get_wordlist (languages [val ].abbr , words );
491501}
492502
493- static void get_mnemonic ( char * mnemonic ) {
503+ static char * get_mnemonic ( void ) {
494504 char * line = NULL ;
495505 size_t line_size = 0 ;
496506
@@ -500,42 +510,53 @@ static void get_mnemonic(char *mnemonic) {
500510 if (characters < 0 )
501511 errx (ERROR_USAGE , "Could not read line from stdin." );
502512 line [characters - 1 ] = '\0' ;
503- strcpy (mnemonic , line );
504- free (line );
513+ return line ;
505514}
506515
507- static void read_mnemonic ( char * mnemonic ) {
516+ static char * read_mnemonic ( void ) {
508517 /* Get words for the mnemonic language */
509518 struct words * words ;
510519 get_words (& words );
511520
512521 /* Get mnemonic */
513- get_mnemonic (mnemonic );
522+ char * mnemonic ;
523+ mnemonic = get_mnemonic ();
514524
515525 if (bip39_mnemonic_validate (words , mnemonic ) != 0 ) {
516526 errx (ERROR_USAGE , "Invalid mnemonic: \"%s\"" , mnemonic );
517527 }
528+ return mnemonic ;
518529}
519530
520- static int generate_hsm (const char * hsm_secret_path )
531+ static int generate_hsm (const char * hsm_secret_path ,
532+ const char * lang_id ,
533+ const char * mnemonic ,
534+ char * passphrase )
521535{
522- char mnemonic [BIP39_WORDLIST_LEN ];
523- char * passphrase ;
524536 const char * err ;
525537 int exit_code = 0 ;
526538
527- read_mnemonic (mnemonic );
528- printf ("Warning: remember that different passphrases yield different "
529- "bitcoin wallets.\n" );
530- printf ("If left empty, no password is used (echo is disabled).\n" );
531- printf ("Enter your passphrase: \n" );
532- fflush (stdout );
533- passphrase = read_stdin_pass_with_exit_code (& err , & exit_code );
534- if (!passphrase )
535- errx (exit_code , "%s" , err );
536- if (strlen (passphrase ) == 0 ) {
537- free (passphrase );
538- passphrase = NULL ;
539+ if (lang_id == NULL ) {
540+ mnemonic = read_mnemonic ();
541+ printf ("Warning: remember that different passphrases yield different "
542+ "bitcoin wallets.\n" );
543+ printf ("If left empty, no password is used (echo is disabled).\n" );
544+ printf ("Enter your passphrase: \n" );
545+ fflush (stdout );
546+ passphrase = read_stdin_pass_with_exit_code (& err , & exit_code );
547+ if (!passphrase )
548+ errx (exit_code , "%s" , err );
549+ if (strlen (passphrase ) == 0 ) {
550+ free (passphrase );
551+ passphrase = NULL ;
552+ }
553+ } else {
554+ struct words * words ;
555+
556+ bip39_get_wordlist (lang_id , & words );
557+
558+ if (bip39_mnemonic_validate (words , mnemonic ) != 0 )
559+ errx (ERROR_USAGE , "Invalid mnemonic: \"%s\"" , mnemonic );
539560 }
540561
541562 u8 bip32_seed [BIP39_SEED_LEN_512 ];
@@ -631,7 +652,7 @@ static int dumponchaindescriptors(const char *hsm_secret_path,
631652
632653static int check_hsm (const char * hsm_secret_path )
633654{
634- char mnemonic [ BIP39_WORDLIST_LEN ] ;
655+ char * mnemonic ;
635656 struct secret hsm_secret ;
636657 u8 bip32_seed [BIP39_SEED_LEN_512 ];
637658 size_t bip32_seed_len ;
@@ -654,7 +675,7 @@ static int check_hsm(const char *hsm_secret_path)
654675 passphrase = NULL ;
655676 }
656677
657- read_mnemonic (mnemonic );
678+ mnemonic = read_mnemonic ();
658679 if (bip39_mnemonic_to_seed (mnemonic , passphrase , bip32_seed , sizeof (bip32_seed ), & bip32_seed_len ) != WALLY_OK )
659680 errx (ERROR_LIBWALLY , "Unable to derive BIP32 seed from BIP39 mnemonic" );
660681
@@ -772,18 +793,28 @@ int main(int argc, char *argv[])
772793 }
773794
774795 if (streq (method , "generatehsm" )) {
775- if (argc != 3 )
796+ // argv[2] file, argv[3] lang_id, argv[4] word list, argv[5] passphrase
797+ if (argc < 3 || argc > 6 || argc == 4 )
776798 show_usage (argv [0 ]);
777799
778800 char * hsm_secret_path = argv [2 ];
801+ char * lang_id , * word_list , * passphrase ;
779802
780803 /* if hsm_secret already exists we abort the process
781804 * we do not want to lose someone else's funds */
782805 struct stat st ;
783806 if (stat (hsm_secret_path , & st ) == 0 )
784807 errx (ERROR_USAGE , "hsm_secret file at %s already exists" , hsm_secret_path );
785808
786- return generate_hsm (hsm_secret_path );
809+ lang_id = (argc > 3 ? argv [3 ] : NULL );
810+ if (lang_id && !check_lang (lang_id ))
811+ show_usage (argv [0 ]);
812+
813+ word_list = (argc > 4 ? argv [4 ] : NULL );
814+ /* generate_hsm expects to free this, so use strdup */
815+ passphrase = (argc > 5 ? strdup (argv [5 ]) : NULL );
816+
817+ return generate_hsm (hsm_secret_path , lang_id , word_list , passphrase );
787818 }
788819
789820 if (streq (method , "dumponchaindescriptors" )) {
0 commit comments