v0.0.2 - Add random mnemonic startup flow and multi-instance random socket naming
This commit is contained in:
@@ -63,8 +63,10 @@ int main(void) {
|
||||
role_entry_t ssh_role;
|
||||
mnemonic_state_t mnemonic;
|
||||
dispatcher_ctx_t dispatcher;
|
||||
key_store_t key_store;
|
||||
const char *valid_12 = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
char *resp;
|
||||
int derived;
|
||||
|
||||
role_table_init(&table);
|
||||
|
||||
@@ -77,27 +79,34 @@ int main(void) {
|
||||
mnemonic_init(&mnemonic);
|
||||
mnemonic_load(&mnemonic, valid_12);
|
||||
|
||||
dispatcher_init(&dispatcher, &table, &mnemonic);
|
||||
memset(&key_store, 0, sizeof(key_store));
|
||||
dispatcher_init(&dispatcher, &table, &mnemonic, &key_store);
|
||||
|
||||
/* 1. Valid get_public_key no selector -> default main, not_yet_derived */
|
||||
derived = crypto_init();
|
||||
check_condition("crypto_init succeeds", derived == 0);
|
||||
|
||||
derived = crypto_derive_all(&key_store, &table, &mnemonic);
|
||||
check_condition("crypto_derive_all derives at least one key", derived >= 1);
|
||||
|
||||
/* 1. Valid get_public_key no selector -> default main, real pubkey */
|
||||
resp = dispatcher_handle_request(&dispatcher,
|
||||
"{\"id\":\"1\",\"method\":\"get_public_key\",\"params\":[\"\"]}");
|
||||
check_condition("get_public_key default role returns not_yet_derived",
|
||||
response_has(resp, "\"id\":\"1\"") && response_has(resp, "\"result\":\"not_yet_derived\""));
|
||||
check_condition("get_public_key default role returns derived hex",
|
||||
response_has(resp, "\"id\":\"1\"") && !response_has(resp, "not_yet_derived") && response_has(resp, "\"result\":\""));
|
||||
free(resp);
|
||||
|
||||
/* 2. sign_event with role main */
|
||||
resp = dispatcher_handle_request(&dispatcher,
|
||||
"{\"id\":\"2\",\"method\":\"sign_event\",\"params\":[\"{}\",{\"role\":\"main\"}]}");
|
||||
check_condition("sign_event with role=main returns stub",
|
||||
response_has(resp, "\"id\":\"2\"") && response_has(resp, "\"result\":\"stub:sign_event_ok\""));
|
||||
"{\"id\":\"2\",\"method\":\"sign_event\",\"params\":[\"{\\\"kind\\\":1,\\\"content\\\":\\\"hello\\\",\\\"tags\\\":[]}\",{\"role\":\"main\"}]}");
|
||||
check_condition("sign_event with role=main returns signed event",
|
||||
response_has(resp, "\"id\":\"2\"") && response_has(resp, "pubkey") && response_has(resp, "sig") && response_has(resp, "created_at"));
|
||||
free(resp);
|
||||
|
||||
/* 3. sign_event with nostr_index 0 */
|
||||
resp = dispatcher_handle_request(&dispatcher,
|
||||
"{\"id\":\"3\",\"method\":\"sign_event\",\"params\":[\"{}\",{\"nostr_index\":0}]}");
|
||||
check_condition("sign_event with nostr_index=0 returns stub",
|
||||
response_has(resp, "\"id\":\"3\"") && response_has(resp, "\"result\":\"stub:sign_event_ok\""));
|
||||
"{\"id\":\"3\",\"method\":\"sign_event\",\"params\":[\"{\\\"kind\\\":1,\\\"content\\\":\\\"hello2\\\",\\\"tags\\\":[]}\",{\"nostr_index\":0}]}");
|
||||
check_condition("sign_event with nostr_index=0 returns signed event",
|
||||
response_has(resp, "\"id\":\"3\"") && response_has(resp, "pubkey") && response_has(resp, "sig") && response_has(resp, "created_at"));
|
||||
free(resp);
|
||||
|
||||
/* 4. ambiguous selector role + nostr_index */
|
||||
@@ -152,7 +161,10 @@ int main(void) {
|
||||
response_has(resp, "\"id\":\"10\"") && response_has(resp, "\"code\":-32601"));
|
||||
free(resp);
|
||||
|
||||
printf("%d/10 tests passed\n", g_passes);
|
||||
crypto_wipe(&key_store);
|
||||
crypto_cleanup();
|
||||
|
||||
return (g_passes == 10 && g_total == 10) ? 0 : 1;
|
||||
printf("%d/12 tests passed\n", g_passes);
|
||||
|
||||
return (g_passes == 12 && g_total == 12) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SOCKET_NAME "nsigner"
|
||||
#define SOCKET_NAME "nsigner_test_run"
|
||||
#define MAX_MSG_SIZE 65536
|
||||
|
||||
static int g_failures = 0;
|
||||
@@ -174,7 +174,7 @@ static int request_roundtrip(const char *req, char **resp) {
|
||||
int main(void) {
|
||||
int stdin_pipe[2];
|
||||
pid_t child;
|
||||
const char *mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about\n\n";
|
||||
const char *mnemonic = "\nabandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about\n";
|
||||
char *resp = NULL;
|
||||
int status;
|
||||
|
||||
@@ -203,7 +203,7 @@ int main(void) {
|
||||
close(stdin_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
|
||||
execl("./build/nsigner", "./build/nsigner", (char *)NULL);
|
||||
execl("./build/nsigner", "./build/nsigner", "--socket-name", SOCKET_NAME, (char *)NULL);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
@@ -226,9 +226,9 @@ int main(void) {
|
||||
free(resp);
|
||||
resp = NULL;
|
||||
|
||||
if (request_roundtrip("{\"id\":\"2\",\"method\":\"sign_event\",\"params\":[\"{}\",{\"role\":\"main\"}]}", &resp) == 0) {
|
||||
if (request_roundtrip("{\"id\":\"2\",\"method\":\"sign_event\",\"params\":[\"{\\\"kind\\\":1,\\\"content\\\":\\\"hello\\\",\\\"tags\\\":[],\\\"created_at\\\":1700000000}\",{\"role\":\"main\"}]}", &resp) == 0) {
|
||||
check_condition("sign_event response id", strstr(resp, "\"id\":\"2\"") != NULL);
|
||||
check_condition("sign_event stub result", strstr(resp, "stub:sign_event_ok") != NULL);
|
||||
check_condition("sign_event has result", strstr(resp, "\"result\":") != NULL);
|
||||
} else {
|
||||
check_condition("sign_event request roundtrip", 0);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ int main(void) {
|
||||
const char *invalid_11 = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
char invalid_25[MNEMONIC_MAX_LEN];
|
||||
const char *loaded_phrase;
|
||||
char generated_12[MNEMONIC_MAX_LEN];
|
||||
char generated_24[MNEMONIC_MAX_LEN];
|
||||
int rc;
|
||||
|
||||
mnemonic_init(&state);
|
||||
@@ -73,6 +75,22 @@ int main(void) {
|
||||
check_condition("reject invalid 25-word mnemonic", rc == -1);
|
||||
check_condition("state remains unloaded after invalid 25-word load", mnemonic_is_loaded(&state) == 0);
|
||||
|
||||
rc = mnemonic_generate(12, generated_12, sizeof(generated_12));
|
||||
check_condition("mnemonic_generate(12) returns 0", rc == 0);
|
||||
check_condition("mnemonic_generate(12) output non-empty", rc == 0 && generated_12[0] != '\0');
|
||||
check_condition("load generated 12-word mnemonic", rc == 0 && mnemonic_load(&state, generated_12) == 0);
|
||||
check_condition("generated 12 word_count == 12", mnemonic_is_loaded(&state) && state.word_count == 12);
|
||||
mnemonic_unload(&state);
|
||||
|
||||
rc = mnemonic_generate(24, generated_24, sizeof(generated_24));
|
||||
check_condition("mnemonic_generate(24) returns 0", rc == 0);
|
||||
check_condition("mnemonic_generate(24) output non-empty", rc == 0 && generated_24[0] != '\0');
|
||||
check_condition("load generated 24-word mnemonic", rc == 0 && mnemonic_load(&state, generated_24) == 0);
|
||||
check_condition("generated 24 word_count == 24", mnemonic_is_loaded(&state) && state.word_count == 24);
|
||||
mnemonic_unload(&state);
|
||||
|
||||
check_condition("two generated mnemonics differ", strcmp(generated_12, generated_24) != 0);
|
||||
|
||||
if (g_failures == 0) {
|
||||
printf("ALL TESTS PASSED\n");
|
||||
return 0;
|
||||
|
||||
51
tests/test_socket_name.c
Normal file
51
tests/test_socket_name.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "../src/socket_name.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int g_failures = 0;
|
||||
|
||||
static void check_condition(const char *name, int condition) {
|
||||
if (condition) {
|
||||
printf("PASS: %s\n", name);
|
||||
} else {
|
||||
printf("FAIL: %s\n", name);
|
||||
g_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
char a[128];
|
||||
char b[128];
|
||||
|
||||
memset(a, 0, sizeof(a));
|
||||
memset(b, 0, sizeof(b));
|
||||
|
||||
check_condition("socket_name_random(a) succeeds", socket_name_random(a, sizeof(a)) == 0);
|
||||
check_condition("socket_name_random(b) succeeds", socket_name_random(b, sizeof(b)) == 0);
|
||||
|
||||
check_condition("name a starts with nsigner_", strncmp(a, "nsigner_", 8) == 0);
|
||||
check_condition("name b starts with nsigner_", strncmp(b, "nsigner_", 8) == 0);
|
||||
|
||||
{
|
||||
const char *suffix = a + 8;
|
||||
const char *underscore = strchr(suffix, '_');
|
||||
check_condition("name a contains second underscore", underscore != NULL && underscore > suffix && underscore[1] != '\0');
|
||||
}
|
||||
|
||||
{
|
||||
const char *suffix = b + 8;
|
||||
const char *underscore = strchr(suffix, '_');
|
||||
check_condition("name b contains second underscore", underscore != NULL && underscore > suffix && underscore[1] != '\0');
|
||||
}
|
||||
|
||||
check_condition("two generated names are typically different", strcmp(a, b) != 0);
|
||||
|
||||
if (g_failures == 0) {
|
||||
printf("ALL TESTS PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("TESTS FAILED: %d\n", g_failures);
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user