diff --git a/src/main.c b/src/main.c index ca98286f..f89624bf 100644 --- a/src/main.c +++ b/src/main.c @@ -62,10 +62,8 @@ static int _tf_command_import(const char* file, int argc, char* argv[]); static int _tf_command_export(const char* file, int argc, char* argv[]); static int _tf_command_run(const char* file, int argc, char* argv[]); static int _tf_command_sandbox(const char* file, int argc, char* argv[]); -static int _tf_command_post(const char* file, int argc, char* argv[]); static int _tf_command_check(const char* file, int argc, char* argv[]); static int _tf_command_usage(const char* file, int argc, char* argv[]); -static int _tf_command_private(const char* file, int argc, char* argv[]); typedef struct _command_t { const char* name; @@ -76,12 +74,10 @@ typedef struct _command_t { const command_t k_commands[] = { { "run", _tf_command_run, "Run tildefriends (default)." }, { "sandbox", _tf_command_sandbox, "Run a sandboxed tildefriends sandbox process (used internally)." }, - { "post", _tf_command_post, "Create an SSB post." }, { "import", _tf_command_import, "Import apps to SSB." }, { "export", _tf_command_export, "Export apps from SSB." }, { "test", _tf_command_test, "Test SSB." }, { "check", _tf_command_check, "Validate messages in the SSB database." }, - { "private", _tf_command_private, "Check for private messages the SSB database (just an experiment)." }, }; const char* k_db_path_default = "db.sqlite"; @@ -522,48 +518,6 @@ xopt_help: return 1; } -static int _tf_command_post(const char* file, int argc, char* argv[]) -{ - typedef struct args_t { - char* message; - bool help; - } args_t; - - xoptOption options[] = { - { "message", 'm', offsetof(args_t, message), NULL, XOPT_REQUIRED | XOPT_TYPE_STRING, "TEXT", "Text to post." }, - { "help", 'h', offsetof(args_t, help), NULL, XOPT_TYPE_BOOL, NULL, "Shows this help message." }, - XOPT_NULLOPTION, - }; - - args_t args = { 0 }; - const char** extras = NULL; - int extra_count = 0; - const char *err = NULL; - XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "post [options]", "options:", NULL, 15); - if (extras) - { - free((void*)extras); - } - if (err) - { - fprintf(stderr, "Error: %s\n", err); - return 2; - } - - tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, k_db_path_default); - tf_ssb_broadcast_listener_start(ssb, false); - tf_ssb_append_post(ssb, args.message); - tf_ssb_destroy(ssb); - return 0; - -xopt_help: - if (extras) - { - free((void*)extras); - } - return 1; -} - static int _tf_command_check(const char* file, int argc, char* argv[]) { typedef struct args_t { @@ -619,51 +573,6 @@ xopt_help: return 1; } -static int _tf_command_private(const char* file, int argc, char* argv[]) -{ - typedef struct args_t { - bool help; - } args_t; - - xoptOption options[] = { - { "help", 'h', offsetof(args_t, help), NULL, XOPT_TYPE_BOOL, NULL, "Shows this help message." }, - XOPT_NULLOPTION, - }; - - args_t args = { 0 }; - const char** extras = NULL; - int extra_count = 0; - const char *err = NULL; - XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "private [options]", "options:", NULL, 15); - if (err) - { - if (extras) - { - free((void*)extras); - } - fprintf(stderr, "Error: %s\n", err); - return 2; - } - - bool result = true; - sqlite3* db = NULL; - sqlite3_open(k_db_path_default, &db); - tf_ssb_db_private(db); - sqlite3_close(db); - if (extras) - { - free((void*)extras); - } - return result ? EXIT_SUCCESS : EXIT_FAILURE; - -xopt_help: - if (extras) - { - free((void*)extras); - } - return 1; -} - static int _tf_command_usage(const char* file, int argc, char* argv[]) { tf_printf("Usage: %s command [command-options]\n", file); diff --git a/src/ssb.c b/src/ssb.c index 43bed668..630fa6d4 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -1735,13 +1735,6 @@ void tf_ssb_append_message_with_keys(tf_ssb_t* ssb, const char* author, const ui JS_FreeValue(context, root); } -void tf_ssb_append_message(tf_ssb_t* ssb, JSValue message) -{ - char author[k_id_base64_len]; - tf_ssb_id_bin_to_str(author, sizeof(author), ssb->pub); - tf_ssb_append_message_with_keys(ssb, author, ssb->priv, message); -} - static void _tf_ssb_connection_dispatch_scheduled(tf_ssb_connection_t* connection) { if (connection->scheduled_count) @@ -2202,6 +2195,11 @@ void tf_ssb_generate_keys_buffer(char* out_public, size_t public_size, char* out snprintf(out_private, private_size, "%s.ed25519", buffer); } +void tf_ssb_get_private_key(tf_ssb_t* ssb, uint8_t* out_private, size_t private_size) +{ + memcpy(out_private, ssb->priv, tf_min(private_size, sizeof(ssb->priv))); +} + void tf_ssb_set_trace(tf_ssb_t* ssb, tf_trace_t* trace) { ssb->trace = trace; @@ -2946,15 +2944,6 @@ void tf_ssb_broadcast_sender_start(tf_ssb_t* ssb) uv_timer_start(&ssb->broadcast_timer, _tf_ssb_broadcast_timer, 2000, 2000); } -void tf_ssb_append_post(tf_ssb_t* ssb, const char* text) -{ - JSValue obj = JS_NewObject(ssb->context); - JS_SetPropertyStr(ssb->context, obj, "type", JS_NewString(ssb->context, "post")); - JS_SetPropertyStr(ssb->context, obj, "text", JS_NewString(ssb->context, text)); - tf_ssb_append_message(ssb, obj); - JS_FreeValue(ssb->context, obj); -} - tf_ssb_connection_t* tf_ssb_connection_get(tf_ssb_t* ssb, const char* id) { uint8_t pub[k_id_bin_len] = { 0 }; diff --git a/src/ssb.db.c b/src/ssb.db.c index 6f1a6ba9..fbae0bb7 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -1139,87 +1139,6 @@ const char** tf_ssb_db_get_all_visible_identities(tf_ssb_t* ssb, int depth) return following; } -static void _test_private(sqlite3* db, const uint8_t* private_key) -{ - sqlite3_stmt* statement = NULL; - if (sqlite3_prepare(db, "SELECT content FROM messages WHERE content LIKE '\"%%.box\"'", -1, &statement, NULL) == SQLITE_OK) - { - while (sqlite3_step(statement) == SQLITE_ROW) - { - uint8_t buffer[8192]; - int r = tf_base64_decode((const char*)sqlite3_column_text(statement, 0) + 1, sqlite3_column_bytes(statement, 0) - strlen("\".box\""), buffer, sizeof(buffer)); - - if (r > 1) - { - uint8_t* nonce = buffer; - uint8_t* public_key = buffer + 24; - if (public_key + 32 < buffer + r) - { - uint8_t shared_secret[crypto_scalarmult_curve25519_SCALARBYTES]; - if (crypto_scalarmult(shared_secret, private_key, public_key) == 0) - { - for (uint8_t* p = buffer + 24 + 32; p <= buffer + r - 49; p += 49) - { - uint8_t out[49]; - int o = crypto_secretbox_open_easy(out, p, 49, nonce, shared_secret); - if (o != -1) - { - int recipients = (int)out[0]; - uint8_t* body = buffer + 24 + 32 + 49 * recipients; - size_t body_size = buffer + r - body; - - uint8_t result[8192]; - - uint8_t* key = out + 1; - if (crypto_secretbox_open_easy(result, body, body_size, nonce, key) != -1) - { - tf_printf("%.*s\n", (int)body_size, result); - } - } - } - } - else - { - tf_printf("scalarmult failed\n"); - } - } - } - else - { - tf_printf("base64 failed\n"); - } - } - sqlite3_finalize(statement); - } -} - -void tf_ssb_db_private(sqlite3* db) -{ - sqlite3_stmt* statement = NULL; - if (sqlite3_prepare(db, "SELECT public_key, private_key FROM identities", -1, &statement, NULL) == SQLITE_OK) - { - while (sqlite3_step(statement) == SQLITE_ROW) - { - uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 }; - tf_printf("-> %s\n", sqlite3_column_text(statement, 0)); - int r = tf_base64_decode((const char*)sqlite3_column_text(statement, 1), sqlite3_column_bytes(statement, 1) - strlen(".ed25519"), private_key, sizeof(private_key)); - if (r == sizeof(private_key)) - { - uint8_t key[crypto_sign_SECRETKEYBYTES] = { 0 }; - if (crypto_sign_ed25519_sk_to_curve25519(key, private_key) != 0) - { - tf_printf("key convert failed\n"); - } - else - { - _test_private(db, key); - } - } - } - sqlite3_finalize(statement); - } -} - JSValue tf_ssb_db_get_message_by_id( tf_ssb_t* ssb, const char* id, bool is_keys) { JSValue result = JS_UNDEFINED; diff --git a/src/ssb.db.h b/src/ssb.db.h index c685762c..b16f75aa 100644 --- a/src/ssb.db.h +++ b/src/ssb.db.h @@ -44,8 +44,6 @@ JSValue tf_ssb_format_message( const char** tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth); const char** tf_ssb_db_get_all_visible_identities(tf_ssb_t* ssb, int depth); -void tf_ssb_db_private(sqlite3* db); - typedef struct _tf_ssb_db_stored_connection_t { char address[256]; diff --git a/src/ssb.h b/src/ssb.h index 50458ac9..168330f2 100644 --- a/src/ssb.h +++ b/src/ssb.h @@ -76,16 +76,13 @@ uv_loop_t* tf_ssb_get_loop(tf_ssb_t* ssb); void tf_ssb_generate_keys(tf_ssb_t* ssb); void tf_ssb_generate_keys_buffer(char* out_public, size_t public_size, char* out_private, size_t private_size); +void tf_ssb_get_private_key(tf_ssb_t* ssb, uint8_t* out_private, size_t private_size); void tf_ssb_set_trace(tf_ssb_t* ssb, tf_trace_t* trace); tf_trace_t* tf_ssb_get_trace(tf_ssb_t* ssb); JSContext* tf_ssb_get_context(tf_ssb_t* ssb); -/* TODO: Delete. */ -void tf_ssb_append_message(tf_ssb_t* ssb, JSValue message); -void tf_ssb_append_post(tf_ssb_t* ssb, const char* text); - void tf_ssb_broadcast_listener_start(tf_ssb_t* ssb, bool linger); void tf_ssb_broadcast_sender_start(tf_ssb_t* ssb); void tf_ssb_run(tf_ssb_t* ssb); diff --git a/src/ssb.tests.c b/src/ssb.tests.c index 1467f6af..abce7438 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -151,6 +151,11 @@ void tf_ssb_test_ssb(const tf_test_options_t* options) tf_ssb_generate_keys(ssb0); tf_ssb_generate_keys(ssb1); + uint8_t priv0[512] = { 0 }; + uint8_t priv1[512] = { 0 }; + tf_ssb_get_private_key(ssb0, priv0, sizeof(priv0)); + tf_ssb_get_private_key(ssb1, priv1, sizeof(priv1)); + char id0[k_id_base64_len] = { 0 }; char id1[k_id_base64_len] = { 0 }; bool b = tf_ssb_whoami(ssb0, id0, sizeof(id0)); @@ -165,20 +170,29 @@ void tf_ssb_test_ssb(const tf_test_options_t* options) b = tf_ssb_db_blob_store(ssb0, (const uint8_t*)k_blob, strlen(k_blob), blob_id, sizeof(blob_id), NULL); assert(b); - tf_ssb_append_post(ssb0, "Hello, world!"); - tf_ssb_append_post(ssb0, "First post."); + JSContext* context0 = tf_ssb_get_context(ssb0); + JSValue obj = JS_NewObject(context0); + JS_SetPropertyStr(context0, obj, "type", JS_NewString(context0, "post")); + JS_SetPropertyStr(context0, obj, "text", JS_NewString(context0, "Hello, world!")); + tf_ssb_append_message_with_keys(ssb0, id0, priv0, obj); + JS_FreeValue(context0, obj); - JSContext* context = tf_ssb_get_context(ssb0); - JSValue message = JS_NewObject(context); - JS_SetPropertyStr(context, message, "type", JS_NewString(context, "post")); - JS_SetPropertyStr(context, message, "text", JS_NewString(context, "First post.")); - JSValue mentions = JS_NewArray(context); - JSValue mention = JS_NewObject(context); - JS_SetPropertyStr(context, mention, "link", JS_NewString(context, blob_id)); - JS_SetPropertyUint32(context, mentions, 0, mention); - JS_SetPropertyStr(context, message, "mentions", mentions); - tf_ssb_append_message(ssb0, message); - JS_FreeValue(context, message); + obj = JS_NewObject(context0); + JS_SetPropertyStr(context0, obj, "type", JS_NewString(context0, "post")); + JS_SetPropertyStr(context0, obj, "text", JS_NewString(context0, "First post.")); + tf_ssb_append_message_with_keys(ssb0, id0, priv0, obj); + JS_FreeValue(context0, obj); + + obj = JS_NewObject(context0); + JS_SetPropertyStr(context0, obj, "type", JS_NewString(context0, "post")); + JS_SetPropertyStr(context0, obj, "text", JS_NewString(context0, "First post.")); + JSValue mentions = JS_NewArray(context0); + JSValue mention = JS_NewObject(context0); + JS_SetPropertyStr(context0, mention, "link", JS_NewString(context0, blob_id)); + JS_SetPropertyUint32(context0, mentions, 0, mention); + JS_SetPropertyStr(context0, obj, "mentions", mentions); + tf_ssb_append_message_with_keys(ssb0, id0, priv0, obj); + JS_FreeValue(context0, obj); uint8_t* b0; size_t s0 = 0; @@ -229,7 +243,13 @@ void tf_ssb_test_ssb(const tf_test_options_t* options) int count1 = 0; tf_ssb_add_message_added_callback(ssb0, _message_added, NULL, &count0); tf_ssb_add_message_added_callback(ssb1, _message_added, NULL, &count1); - tf_ssb_append_post(ssb0, "Message to self."); + + obj = JS_NewObject(context0); + JS_SetPropertyStr(context0, obj, "type", JS_NewString(context0, "post")); + JS_SetPropertyStr(context0, obj, "text", JS_NewString(context0, "Message to self.")); + tf_ssb_append_message_with_keys(ssb0, id0, priv0, obj); + JS_FreeValue(context0, obj); + while (count0 == 0) { uv_run(&loop, UV_RUN_ONCE); @@ -461,16 +481,23 @@ void tf_ssb_test_following(const tf_test_options_t* options) tf_ssb_whoami(ssb1, id1, sizeof(id1)); tf_ssb_whoami(ssb2, id2, sizeof(id2)); + uint8_t priv0[512] = { 0 }; + uint8_t priv1[512] = { 0 }; + uint8_t priv2[512] = { 0 }; + tf_ssb_get_private_key(ssb0, priv0, sizeof(priv0)); + tf_ssb_get_private_key(ssb1, priv1, sizeof(priv1)); + tf_ssb_get_private_key(ssb2, priv2, sizeof(priv2)); + JSContext* context = NULL; JSValue message; - #define FOLLOW(ssb, id, follow) \ + #define FOLLOW(ssb, id, priv, follow) \ context = tf_ssb_get_context(ssb); \ message = JS_NewObject(context); \ JS_SetPropertyStr(context, message, "type", JS_NewString(context, "contact")); \ JS_SetPropertyStr(context, message, "contact", JS_NewString(context, id)); \ JS_SetPropertyStr(context, message, "following", follow ? JS_TRUE : JS_FALSE); \ - tf_ssb_append_message(ssb, message); \ + tf_ssb_append_message_with_keys(ssb, id, priv, message); \ JS_FreeValue(context, message); \ context = NULL @@ -494,18 +521,18 @@ void tf_ssb_test_following(const tf_test_options_t* options) while (0) #endif - FOLLOW(ssb0, id1, true); - FOLLOW(ssb1, id2, true); - FOLLOW(ssb2, id0, true); + FOLLOW(ssb0, id1, priv1, true); + FOLLOW(ssb1, id2, priv2, true); + FOLLOW(ssb2, id0, priv0, true); DUMP(id0, 2); DUMP(id1, 2); DUMP(id2, 2); - FOLLOW(ssb0, id1, false); - //FOLLOW(ssb0, id1, true); - //FOLLOW(ssb0, id1, true); + FOLLOW(ssb0, id1, priv1, false); + //FOLLOW(ssb0, id1, priv1, true); + //FOLLOW(ssb0, id1, priv1, true); DUMP(id0, 1); DUMP(id1, 2); - //FOLLOW(ssb0, id1, false); + //FOLLOW(ssb0, id1, priv1, false); //DUMP(1); //DUMP(1); @@ -534,14 +561,21 @@ void tf_ssb_test_bench(const tf_test_options_t* options) char id0[k_id_base64_len] = { 0 }; tf_ssb_whoami(ssb0, id0, sizeof(id0)); + uint8_t priv0[512]; + tf_ssb_get_private_key(ssb0, priv0, sizeof(priv0)); + struct timespec start_time = { 0 }; struct timespec end_time = { 0 }; clock_gettime(CLOCK_REALTIME, &start_time); const int k_messages = 4096; + JSValue obj = JS_NewObject(tf_ssb_get_context(ssb0)); + JS_SetPropertyStr(tf_ssb_get_context(ssb0), obj, "type", JS_NewString(tf_ssb_get_context(ssb0), "post")); + JS_SetPropertyStr(tf_ssb_get_context(ssb0), obj, "text", JS_NewString(tf_ssb_get_context(ssb0), "Hello, world!")); for (int i = 0; i < k_messages; i++) { - tf_ssb_append_post(ssb0, "Hello, world!"); + tf_ssb_append_message_with_keys(ssb0, id0, priv0, obj); } + JS_FreeValue(tf_ssb_get_context(ssb0), obj); clock_gettime(CLOCK_REALTIME, &end_time); tf_printf("insert = %f seconds\n", (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1e9); diff --git a/src/util.js.h b/src/util.js.h index d43169d1..7349e283 100644 --- a/src/util.js.h +++ b/src/util.js.h @@ -21,3 +21,5 @@ const char* tf_util_backtrace_to_string(void* const* buffer, int count); const char* tf_util_backtrace_string(); const char* tf_util_function_to_string(void* function); + + #define tf_min(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })