Skip to content

Commit

Permalink
utils: added getpass
Browse files Browse the repository at this point in the history
spvnode: added getpass, clear and free for passphrase and error handling
such: added getpass, clear and free for passphrase
doc: updated passphrase in tools.md
seal: removed getpass
wallet: updated init exits to returns for error handling
  • Loading branch information
edtubbs committed Nov 13, 2023
1 parent ce9b2bf commit 66a2dc3
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 100 deletions.
2 changes: 1 addition & 1 deletion doc/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Most of these commands require a flag following them to denote things like exist
| -m, --derived_path | derived_path | yes | derive_child_key -p <extended_private_key> -m <derived_path> |
| -e, --entropy | hex_entropy | yes | generate_mnemonic -e <hex_entropy> |
| -n, --mnemonic | seed_phrase | yes | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> |
| -a, --pass_phrase | pass_phrase | yes | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> -a <pass_phrase> |
| -a, --pass_phrase | pass_phrase | no | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> -a |
| -o, --account_int | account_int | yes | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> -o <account_int> |
| -g, --change_level | change_level | yes | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> -g <change_level> |
| -i, --address_index | address_index | yes | mnemonic_to_key or mnemonic_to_addresses -n <seed_phrase> -i <address_index> |
Expand Down
4 changes: 3 additions & 1 deletion include/dogecoin/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#define TO_UINT8_HEX_BUF_LEN 2048
#define VARINT_LEN 20
#define MAX_LEN 128

#define BEGIN(a) ((char*)&(a))
#define END(a) ((char*)&((&(a))[1]))
Expand Down Expand Up @@ -82,6 +83,7 @@ LIBDOGECOIN_API char* concat(char* prefix, char* suffix);
LIBDOGECOIN_API void slice(const char *str, char *result, size_t start, size_t end);
LIBDOGECOIN_API void text_to_hex(char* in, char* out);
LIBDOGECOIN_API const char* get_build();
LIBDOGECOIN_API char* getpass(const char *prompt);
LIBDOGECOIN_API void dogecoin_str_reverse(char s[]);
LIBDOGECOIN_API void dogecoin_uitoa(int n, char s[]);
LIBDOGECOIN_API bool dogecoin_network_enabled();
Expand Down Expand Up @@ -115,7 +117,7 @@ static inline void dogecoin_btree_tdestroy(void *root, void (*freekey)(void *))
if (freekey) goto end;
if (r->left && !freekey) dogecoin_btree_tdestroy(r->left, freekey);
if (r->right && !freekey) dogecoin_btree_tdestroy(r->right, freekey);

end:
if (freekey) freekey(r->key);
dogecoin_free(r);
Expand Down
30 changes: 22 additions & 8 deletions src/cli/spvnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static struct option long_options[] = {
{"debug", no_argument, NULL, 'd'},
{"maxnodes", no_argument, NULL, 'm'},
{"mnemonic", no_argument, NULL, 'n'},
{"pass_phrase", required_argument, NULL, 's'},
{"pass_phrase", no_argument, NULL, 's'},
{"dbfile", no_argument, NULL, 'f'},
{"continuous", no_argument, NULL, 'c'},
{"address", no_argument, NULL, 'a'},
Expand All @@ -198,7 +198,7 @@ static void print_version() {
static void print_usage() {
print_version();
printf("Usage: spvnode (-c|continuous) (-i|-ips <ip,ip,...]>) (-m[--maxpeers] <int>) (-t[--testnet]) (-f <headersfile|0 for in mem only>) \
(-n|-mnemonic <seed_phrase>) (-s|-pass_phrase <pass_phrase>) (-y|-encrypted_file <file_num 0-999>) (-w|-wallet_file <filename>) (-h|-headers_file <filename>) \
(-n|-mnemonic <seed_phrase>) (-s|-pass_phrase) (-y|-encrypted_file <file_num 0-999>) (-w|-wallet_file <filename>) (-h|-headers_file <filename>) \
(-k[--master_key] (-j[--use_tpm]) (-r[--regtest]) (-d[--debug]) (-s[--timeout] <secs>) <command>\n");
printf("Supported commands:\n");
printf(" scan (scan blocks up to the tip, creates header.db file)\n");
Expand All @@ -215,10 +215,10 @@ static void print_usage() {
printf("> spvnode -d -c -w \"./wallets/main_wallet.db\" -h \"./headers/main_headers.db\" scan\n\n");
printf("Sync up, with encrypted mnemonic 0, show debug info, don't store headers in file, wait for new blocks:\n");
printf("> spvnode -d -f 0 -c -y 0 scan\n\n");
printf("Sync up, with encrypted mnemonic 0, pass phrase 'test', show debug info, don't store headers in file, wait for new blocks:\n");
printf("> spvnode -d -f 0 -c -y 0 -a \"test\" scan\n\n");
printf("Sync up, with mnemonic 'test', pass phrase 'test', show debug info, don't store headers in file, wait for new blocks:\n");
printf("> spvnode -d -f 0 -c -n \"test\" -a \"test\" scan\n\n");
printf("Sync up, with encrypted mnemonic 0, BIP39 passphrase, show debug info, don't store headers in file, wait for new blocks:\n");
printf("> spvnode -d -f 0 -c -y 0 -a scan\n\n");
printf("Sync up, with mnemonic 'test', BIP39 passphrase, show debug info, don't store headers in file, wait for new blocks:\n");
printf("> spvnode -d -f 0 -c -n \"test\" -a scan\n\n");
}


Expand Down Expand Up @@ -286,7 +286,7 @@ int main(int argc, char* argv[]) {
data = argv[argc - 1];

/* get arguments */
while ((opt = getopt_long_only(argc, argv, "i:ctrds:m:n:f:y:a:w:h:bpzkj:", long_options, &long_index)) != -1) {
while ((opt = getopt_long_only(argc, argv, "i:ctrds:m:n:f:y:w:h:abpzkj:", long_options, &long_index)) != -1) {
switch (opt) {
case 'c':
quit_when_synced = false;
Expand All @@ -304,7 +304,7 @@ int main(int argc, char* argv[]) {
ips = optarg;
break;
case 's':
pass = optarg;
pass = getpass("BIP39 passphrase: \n");
break;
case 'n':
mnemonic_in = optarg;
Expand Down Expand Up @@ -358,6 +358,20 @@ int main(int argc, char* argv[]) {

#if WITH_WALLET
dogecoin_wallet* wallet = dogecoin_wallet_init(chain, address, name, mnemonic_in, pass, encrypted, tpm, file_num, master_key);
if (!wallet) {
printf("Could not initialize wallet...\n");
// clear and free the passphrase
if (pass) {
dogecoin_mem_zero (pass, strlen(pass));
dogecoin_free(pass);
}
return EXIT_FAILURE;
}
// clear and free the passphrase
if (pass) {
dogecoin_mem_zero (pass, strlen(pass));
dogecoin_free(pass);
}
print_utxos(wallet);
client->sync_transaction = dogecoin_wallet_check_transaction;
client->sync_transaction_ctx = wallet;
Expand Down
60 changes: 45 additions & 15 deletions src/cli/such.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ static struct option long_options[] =
{"derived_path", required_argument, NULL, 'm'},
{"entropy", required_argument, NULL, 'e'},
{"mnemonic", required_argument, NULL, 'n'},
{"pass_phrase", required_argument, NULL, 'a'},
{"pass_phrase", no_argument, NULL, 'a'},
{"account_int", required_argument, NULL, 'o'},
{"change_level", required_argument, NULL, 'g'},
{"address_index", required_argument, NULL, 'i'},
Expand All @@ -638,7 +638,7 @@ static void print_usage()
{
print_version();
printf("Usage: such -c <cmd> (-m|-derived_path <bip_derived_path>) (-k|-pubkey <publickey>) (-p|-privkey <privatekey>) \
(-e|-entropy <hex_entropy>) (-n|-mnemonic <seed_phrase>) (-a|-pass_phrase <pass_phrase>) (-y|-encrypted_file <file_num 0-999>) (-w[--overwrite]) (-b[--silent]) \
(-e|-entropy <hex_entropy>) (-n|-mnemonic <seed_phrase>) (-a|-pass_phrase) (-y|-encrypted_file <file_num 0-999>) (-w[--overwrite]) (-b[--silent]) \
(-j[--use_tpm]) (-t[--testnet]) (-r[--regtest])\n");
printf("Available commands:\n");
printf("generate_public_key (requires -p <wif>),\n");
Expand All @@ -649,8 +649,8 @@ static void print_usage()
printf("list_encryption_keys_in_tpm,\n");
printf("decrypt_master_key (requires -y <file_num>, -j (use_tpm) optional),\n");
printf("decrypt_mnemonic (requires -y <file_num>, -j (use_tpm) optional),\n");
printf("mnemonic_to_key (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase>, all optional),\n");
printf("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase>, all optional),\n");
printf("mnemonic_to_key (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a, all optional),\n");
printf("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a, all optional),\n");
printf("print_keys (requires -p <private key hex>),\n");
printf("derive_child_keys (requires -m <custom path> -p <private key>),\n");
printf("sign (-x <raw hex tx> -s <script pubkey> -i <input index> -h <sighash type> -p <private key>),\n");
Expand Down Expand Up @@ -700,7 +700,7 @@ int main(int argc, char* argv[])
const dogecoin_chainparams* chain = &dogecoin_chainparams_main;

/* get arguments */
while ((opt = getopt_long_only(argc, argv, "h:i:s:x:p:k:m:o:g:e:n:a:y:c:trvbwj", long_options, &long_index)) != -1) {
while ((opt = getopt_long_only(argc, argv, "h:i:s:x:p:k:m:o:g:e:n:y:c:atrvbwj", long_options, &long_index)) != -1) {
switch (opt) {
case 'p':
pkey = optarg;
Expand Down Expand Up @@ -728,7 +728,7 @@ int main(int argc, char* argv[])
mnemonic_in = optarg;
break;
case 'a':
pass = optarg;
pass = getpass("BIP39 passphrase: \n");
break;
case 'k':
pubkey = optarg;
Expand Down Expand Up @@ -855,7 +855,7 @@ int main(int argc, char* argv[])
if (overwrite) {
printf("Overwrite? Y/N\n");

char buffer[2];
char buffer[MAX_LEN];
/* get user input */
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
if (buffer[0] != 'Y' && buffer[0] != 'y') {
Expand Down Expand Up @@ -1135,7 +1135,7 @@ int main(int argc, char* argv[])
if (overwrite) {
printf("Overwrite? Y/N\n");

char buffer[2];
char buffer[MAX_LEN];
/* get user input */
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
if (buffer[0] != 'Y' && buffer[0] != 'y') {
Expand Down Expand Up @@ -1203,7 +1203,7 @@ int main(int argc, char* argv[])
if (encrypted) {
printf("Decrypt master key? Y/N\n");

char buffer[2];
char buffer[MAX_LEN];
/* get user input */
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
if (buffer[0] != 'Y' && buffer[0] != 'y') {
Expand Down Expand Up @@ -1253,7 +1253,7 @@ int main(int argc, char* argv[])
if (encrypted) {
printf("Decrypt mnemonic? Y/N\n");

char buffer[2];
char buffer[MAX_LEN];
/* get user input */
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
if (buffer[0] != 'Y' && buffer[0] != 'y') {
Expand Down Expand Up @@ -1338,9 +1338,21 @@ int main(int argc, char* argv[])
/* generate seed from mnemonic */
if (dogecoin_seed_from_mnemonic(encrypted ? mnemonic : mnemonic_in, pass, seed) == -1) {
printf("mnemonic_to_key (-n <seed_phrase> or requires -y <file_num>, -j (use_tpm) optional),\n");

/* clear and free passphrase */
if (pass) {
dogecoin_mem_zero(pass, strlen(pass));
dogecoin_free(pass);
}
return showError("failed to generate seed from mnemonic\n");
}

/* clear and free passphrase */
if (pass) {
dogecoin_mem_zero(pass, strlen(pass));
dogecoin_free(pass);
}

/* generate master key from seed */
dogecoin_hdnode_from_seed(seed, sizeof(seed), &node);

Expand All @@ -1361,7 +1373,7 @@ int main(int argc, char* argv[])
if (encrypted) {
printf("Decrypt mnemonic for addresses? Y/N\n");

char buffer[2];
char buffer[MAX_LEN];
/* get user input */
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
if (buffer[0] != 'Y' && buffer[0] != 'y') {
Expand All @@ -1376,23 +1388,23 @@ int main(int argc, char* argv[])
if (tpm) {
/* get mnemonic from tpm */
if (!dogecoin_decrypt_mnemonic_with_tpm (mnemonic, file_num)) {
printf("mnemonic_to_addresses (requires -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase>, all optional),\n");
printf("mnemonic_to_addresses (requires -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a, all optional),\n");
return showError("failed to decrypt mnemonic with tpm\n");
}
}

else {
/* get mnemonic from software */
if (dogecoin_decrypt_mnemonic_with_sw (mnemonic, file_num) == false) {
printf("mnemonic_to_addresses (requires -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase>, all optional),\n");
printf("mnemonic_to_addresses (requires -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a, all optional),\n");
return showError("failed to decrypt mnemonic with software\n");
}
}
}

/* else display usage */
else if (!mnemonic_in) {
return showError("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase> (all optional))\n");
return showError("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a (all optional))\n");
}

/* generate wif address for slip44 account, index, and change_level, from bip39 mnemonic and password (optional) */
Expand All @@ -1401,6 +1413,12 @@ int main(int argc, char* argv[])
/* Generate all addresses for the account. */
for (int i = 0; i < 20; i++) {
if (getDerivedHDAddressFromMnemonic(account, i, change_level, encrypted ? mnemonic : mnemonic_in, pass, hd_pubkey_address, (chain == &dogecoin_chainparams_test)) == -1) {

/* clear and free passphrase */
if (pass) {
dogecoin_mem_zero(pass, strlen(pass));
dogecoin_free(pass);
}
return showError("Failed to generate wif address from mnemonic\n");
}
printf("Address %d: %s\n", i, hd_pubkey_address);
Expand All @@ -1410,12 +1428,24 @@ int main(int argc, char* argv[])

/* Generate a single address for the account. */
if (getDerivedHDAddressFromMnemonic(account, inputindex, change_level, encrypted ? mnemonic : mnemonic_in, pass, hd_pubkey_address, (chain == &dogecoin_chainparams_test)) == -1) {
printf("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a <pass_phrase>, all optional),\n");
printf("mnemonic_to_addresses (requires -n <seed_phrase> or -y <file_num>, -j (use_tpm), -o <account_int>, -g <change_level>, -i <address_index> and -a, all optional),\n");

/* clear and free passphrase */
if (pass) {
dogecoin_mem_zero(pass, strlen(pass));
dogecoin_free(pass);
}
return showError("Failed to generate wif address from mnemonic\n");
}

printf("Address %d: %s\n", inputindex, hd_pubkey_address);
}

/* clear and free passphrase */
if (pass) {
dogecoin_mem_zero(pass, strlen(pass));
dogecoin_free(pass);
}
}
else if (strcmp(cmd, "signmessage") == 0) {
// ./such -c signmessage -x "<message>" -p <private key>
Expand Down
62 changes: 0 additions & 62 deletions src/seal.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,68 +90,6 @@ dogecoin_bool fileValid (const int file_num)

}

/**
* @brief Gets a password from the user
*
* Gets a password from the user without echoing the input to the console.
*
* @param[in] prompt The prompt to display to the user
* @return The password entered by the user
*/
#ifndef TEST_PASSWD
char *getpass(const char *prompt) {
char buffer[PASS_MAX_LEN] = {0}; // Initialize to zero

#ifdef _WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode, count;

if (!GetConsoleMode(hStdin, &mode) || !SetConsoleMode(hStdin, mode & ~ENABLE_ECHO_INPUT))
return NULL;

printf("%s", prompt);
fflush(stdout);

if (!ReadConsole(hStdin, buffer, sizeof(buffer) - 1, &count, NULL))
return NULL; // -1 to ensure null-termination

if (!SetConsoleMode(hStdin, mode))
return NULL;

buffer[count] = '\0'; // Ensure null-termination

#else
struct termios old, new;
ssize_t nread;

if (tcgetattr(STDIN_FILENO, &old) != 0)
return NULL;

new = old;
new.c_lflag &= ~ECHO;

if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new) != 0)
return NULL;

printf("%s", prompt);
fflush(stdout);

if (!fgets(buffer, sizeof(buffer), stdin))
return NULL;

nread = strlen(buffer);
if (nread > 0 && buffer[nread-1] == '\n')
buffer[nread-1] = '\0'; // Remove newline character

if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old) != 0)
return NULL;

#endif

return strdup(buffer);
}
#endif

/**
* @brief Encrypts a seed using the TPM
*
Expand Down
Loading

0 comments on commit 66a2dc3

Please sign in to comment.