verify: Add an option to dump a specific message in the format that its signature validates as well as a hex representation of the bytes for good measure.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 31m2s
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 31m2s
This commit is contained in:
parent
a8bba324ca
commit
d6926569c6
@ -13,6 +13,9 @@
|
||||
|
||||
#include "quickjs.h"
|
||||
|
||||
/**
|
||||
** An HTTP server instance.
|
||||
*/
|
||||
typedef struct _tf_http_t tf_http_t;
|
||||
|
||||
/**
|
||||
|
12
src/main.c
12
src/main.c
@ -1161,17 +1161,19 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
const char* identity = NULL;
|
||||
const char* default_db_path = _get_db_path();
|
||||
const char* db_path = default_db_path;
|
||||
int64_t sequence = 0;
|
||||
bool show_usage = false;
|
||||
|
||||
while (!show_usage)
|
||||
{
|
||||
static const struct option k_options[] = {
|
||||
{ "id", required_argument, NULL, 'i' },
|
||||
{ "sequence", required_argument, NULL, 's' },
|
||||
{ "db-path", required_argument, NULL, 'd' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0 },
|
||||
};
|
||||
int c = getopt_long(argc, argv, "i:d:h", k_options, NULL);
|
||||
int c = getopt_long(argc, argv, "i:s:d:h", k_options, NULL);
|
||||
if (c == -1)
|
||||
{
|
||||
break;
|
||||
@ -1187,6 +1189,9 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
case 'i':
|
||||
identity = optarg;
|
||||
break;
|
||||
case 's':
|
||||
sequence = atoll(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
db_path = optarg;
|
||||
break;
|
||||
@ -1198,6 +1203,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
tf_printf("\n%s import [options] [paths...]\n\n", file);
|
||||
tf_printf("options:\n");
|
||||
tf_printf(" -i, --identity identity Identity to verify.\n");
|
||||
tf_printf(" -s, --sequence sequence Sequence number to debug.\n");
|
||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||
tf_printf(" -h, --help Show this usage information.\n");
|
||||
tf_free((void*)default_db_path);
|
||||
@ -1209,7 +1215,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
if (identity)
|
||||
{
|
||||
tf_printf("Verifying %s...\n", identity);
|
||||
verified = tf_ssb_db_verify(ssb, identity, true);
|
||||
verified = tf_ssb_db_verify(ssb, identity, sequence, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1222,7 +1228,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
{
|
||||
const char* identity = (const char*)sqlite3_column_text(statement, 0);
|
||||
tf_printf("Verifying %s...", identity);
|
||||
if (tf_ssb_db_verify(ssb, identity, true))
|
||||
if (tf_ssb_db_verify(ssb, identity, sequence, true))
|
||||
{
|
||||
tf_printf("success.\n");
|
||||
}
|
||||
|
22
src/ssb.c
22
src/ssb.c
@ -1076,7 +1076,8 @@ void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_
|
||||
JS_FreeValue(context, idval);
|
||||
}
|
||||
|
||||
static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size)
|
||||
static bool _tf_ssb_verify_and_strip_signature_internal(
|
||||
JSContext* context, JSValue val, int verify_flags, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size)
|
||||
{
|
||||
JSValue signature = JS_GetPropertyStr(context, val, "signature");
|
||||
if (JS_IsUndefined(signature))
|
||||
@ -1124,6 +1125,16 @@ static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSVa
|
||||
{
|
||||
r = crypto_sign_verify_detached(binsig, (const uint8_t*)sigstr, strlen(sigstr), publickey);
|
||||
verified = r == 0;
|
||||
if (verify_flags & k_tf_ssb_verify_flag_debug)
|
||||
{
|
||||
tf_printf("verifying author=%s id=%s signature=%s success=%d\n", author, out_id, str, verified);
|
||||
tf_printf("signed string:\n%s\n\n", sigstr);
|
||||
for (int i = 0; sigstr[i]; i++)
|
||||
{
|
||||
tf_printf("%s%02x", (i && (i % 32) == 0) ? "\n" : (i && (i % 8) == 0) ? " " : (i ? " " : ""), sigstr[i]);
|
||||
}
|
||||
tf_printf("\n");
|
||||
}
|
||||
if (!verified)
|
||||
{
|
||||
// tf_printf("crypto_sign_verify_detached fail (r=%d)\n", r);
|
||||
@ -1161,7 +1172,8 @@ static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSVa
|
||||
return verified;
|
||||
}
|
||||
|
||||
bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags)
|
||||
bool tf_ssb_verify_and_strip_signature(
|
||||
JSContext* context, JSValue val, int verify_flags, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags)
|
||||
{
|
||||
JSValue reordered = JS_NewObject(context);
|
||||
JS_SetPropertyStr(context, reordered, "previous", JS_GetPropertyStr(context, val, "previous"));
|
||||
@ -1171,7 +1183,7 @@ bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* ou
|
||||
JS_SetPropertyStr(context, reordered, "hash", JS_GetPropertyStr(context, val, "hash"));
|
||||
JS_SetPropertyStr(context, reordered, "content", JS_GetPropertyStr(context, val, "content"));
|
||||
JS_SetPropertyStr(context, reordered, "signature", JS_GetPropertyStr(context, val, "signature"));
|
||||
bool result = _tf_ssb_verify_and_strip_signature_internal(context, reordered, out_id, out_id_size, out_signature, out_signature_size);
|
||||
bool result = _tf_ssb_verify_and_strip_signature_internal(context, reordered, verify_flags, out_id, out_id_size, out_signature, out_signature_size);
|
||||
JS_FreeValue(context, reordered);
|
||||
|
||||
if (result)
|
||||
@ -1191,7 +1203,7 @@ bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* ou
|
||||
JS_SetPropertyStr(context, reordered, "hash", JS_GetPropertyStr(context, val, "hash"));
|
||||
JS_SetPropertyStr(context, reordered, "content", JS_GetPropertyStr(context, val, "content"));
|
||||
JS_SetPropertyStr(context, reordered, "signature", JS_GetPropertyStr(context, val, "signature"));
|
||||
result = _tf_ssb_verify_and_strip_signature_internal(context, reordered, out_id, out_id_size, out_signature, out_signature_size);
|
||||
result = _tf_ssb_verify_and_strip_signature_internal(context, reordered, verify_flags, out_id, out_id_size, out_signature, out_signature_size);
|
||||
JS_FreeValue(context, reordered);
|
||||
if (result)
|
||||
{
|
||||
@ -4162,7 +4174,7 @@ void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_
|
||||
};
|
||||
char signature[crypto_sign_BYTES + 128] = { 0 };
|
||||
int flags = 0;
|
||||
if (tf_ssb_verify_and_strip_signature(context, value, async->id, sizeof(async->id), signature, sizeof(signature), &flags))
|
||||
if (tf_ssb_verify_and_strip_signature(context, value, 0, async->id, sizeof(async->id), signature, sizeof(signature), &flags))
|
||||
{
|
||||
async->verified = true;
|
||||
tf_ssb_db_store_message(ssb, context, async->id, value, signature, flags, _tf_ssb_verify_strip_and_store_callback, async);
|
||||
|
@ -2154,7 +2154,7 @@ static void _tf_ssb_db_set_flags(tf_ssb_t* ssb, const char* message_id, int flag
|
||||
tf_ssb_release_db_writer(ssb, db);
|
||||
}
|
||||
|
||||
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, bool fix)
|
||||
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, bool fix)
|
||||
{
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
bool verified = true;
|
||||
@ -2177,7 +2177,8 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, bool fix)
|
||||
char calculated_id[k_id_base64_len];
|
||||
char extracted_signature[256];
|
||||
int calculated_flags = 0;
|
||||
if (!tf_ssb_verify_and_strip_signature(context, message, calculated_id, sizeof(calculated_id), extracted_signature, sizeof(extracted_signature), &calculated_flags))
|
||||
if (!tf_ssb_verify_and_strip_signature(context, message, i == debug_sequence ? k_tf_ssb_verify_flag_debug : 0, calculated_id, sizeof(calculated_id),
|
||||
extracted_signature, sizeof(extracted_signature), &calculated_flags))
|
||||
{
|
||||
tf_printf("author=%s sequence=%" PRId64 " verify failed.\n", id, i);
|
||||
verified = false;
|
||||
|
@ -444,10 +444,11 @@ void tf_ssb_db_resolve_index_async(tf_ssb_t* ssb, const char* host, void (*callb
|
||||
** Verify an author's feed.
|
||||
** @param ssb The SSB instance.
|
||||
** @param id The author'd identity.
|
||||
** @param debug_sequence Message sequence number to debug if non-zero.
|
||||
** @param fix Fix invalid messages when possible.
|
||||
** @return true If the feed verified successfully.
|
||||
*/
|
||||
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, bool fix);
|
||||
bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id, int64_t debug_sequence, bool fix);
|
||||
|
||||
/**
|
||||
** Check if a user has a specific permission.
|
||||
|
12
src/ssb.h
12
src/ssb.h
@ -34,6 +34,14 @@ enum
|
||||
k_max_private_message_recipients = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
** Flags affecting signature verification.
|
||||
*/
|
||||
typedef enum _tf_ssb_verify_flags_t
|
||||
{
|
||||
k_tf_ssb_verify_flag_debug = 1,
|
||||
} tf_ssb_verify_flags_t;
|
||||
|
||||
/**
|
||||
** The type of change to a set of connections.
|
||||
*/
|
||||
@ -446,6 +454,7 @@ bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin);
|
||||
** Verify a message's signature and remove the signature if successful.
|
||||
** @param context A JS context.
|
||||
** @param val The message.
|
||||
** @param verify_flags Verification options of type tf_ssb_verify_flags_t.
|
||||
** @param[out] out_id A buffer to receive the message's identity.
|
||||
** @param out_id_size The size of out_id.
|
||||
** @param[out] out_signature A buffer to receive the message's signature.
|
||||
@ -453,7 +462,8 @@ bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin);
|
||||
** @param[out] out_flags tf_ssb_message_flags_t describing the message.
|
||||
** @return True if the signature is valid and was successfully extracted.
|
||||
*/
|
||||
bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags);
|
||||
bool tf_ssb_verify_and_strip_signature(
|
||||
JSContext* context, JSValue val, int verify_flags, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags);
|
||||
|
||||
/**
|
||||
** Determine the message identifier.
|
||||
|
Loading…
x
Reference in New Issue
Block a user