Message IDs are apparently generated from the latin1 encoding of a message. Added a command to check/fix that.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3833 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2022-02-10 03:58:33 +00:00
parent 557ae6ee5a
commit d4135f7133
6 changed files with 205 additions and 13 deletions

View File

@ -477,26 +477,76 @@ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags,
connection->ssb->rpc_out++;
}
static int _utf8_len(uint8_t ch)
{
static const uint8_t k_length[] =
{
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4
};
return k_length[(ch & 0xf0) >> 4];
}
static uint32_t _utf8_decode(uint32_t c)
{
if (c > 0x7f)
{
uint32_t mask = (c <= 0x00efbfbf) ? 0x000f0000 : 0x003f0000;
c = ((c & 0x07000000) >> 6) |
((c & mask) >> 4) |
((c & 0x00003f00) >> 2) |
(c & 0x0000003f);
}
return c;
}
static const uint8_t* _utf8_to_cp(const uint8_t* ch, uint32_t* out_cp)
{
int len = _utf8_len(*ch);
int actual_len = 0;
uint32_t encoding = 0;
for (int i = 0; i < len && ch[i]; i++, actual_len++)
{
encoding = (encoding << 8) | ch[i];
}
*out_cp = _utf8_decode(encoding);
return ch + actual_len;
}
void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_id, size_t out_id_size)
{
JSValue idval = JS_JSONStringify(context, message, JS_NULL, JS_NewInt32(context, 2));
size_t len = 0;
const char* messagestr = JS_ToCStringLen(context, &len, idval);
char* latin1 = strdup(messagestr);
uint8_t* write_pos = (uint8_t*)latin1;
const uint8_t* p = (const uint8_t*)messagestr;
while (p && *p)
{
uint32_t cp = 0;
p = _utf8_to_cp(p, &cp);
*write_pos++ = (cp & 0xff);
}
size_t latin1_len = write_pos - (uint8_t*)latin1;
*write_pos++ = '\0';
uint8_t id[crypto_hash_sha256_BYTES];
crypto_hash_sha256(id, (uint8_t*)messagestr, len);
crypto_hash_sha256(id, (uint8_t*)latin1, latin1_len);
char id_base64[k_id_base64_len];
base64c_encode(id, sizeof(id), (uint8_t*)id_base64, sizeof(id_base64));
snprintf(out_id, out_id_size, "%%%s.sha256", id_base64);
free(latin1);
JS_FreeCString(context, messagestr);
JS_FreeValue(context, idval);
}
static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSValue val, char* out_signature, size_t out_signature_size)
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)
{
bool verified = false;
tf_ssb_calculate_message_id(context, val, out_id, out_id_size);
JSValue signature = JS_GetPropertyStr(context, val, "signature");
const char* str = JS_ToCString(context, signature);
JSAtom sigatom = JS_NewAtom(context, "signature");
@ -530,7 +580,7 @@ static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSVa
verified = r == 0;
if (!verified)
{
printf("crypto_sign_verify_detached fail (r=%d)\n", r);
//printf("crypto_sign_verify_detached fail (r=%d)\n", r);
if (false)
{
printf("val=[%.*s]\n", (int)strlen(sigstr), sigstr);
@ -565,9 +615,9 @@ 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_signature, size_t out_signature_size, bool* out_sequence_before_author)
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, bool* out_sequence_before_author)
{
if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_signature, out_signature_size))
if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_id, out_id_size, out_signature, out_signature_size))
{
if (out_sequence_before_author)
{
@ -585,7 +635,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_signature, out_signature_size);
bool result = _tf_ssb_verify_and_strip_signature_internal(context, reordered, out_id, out_id_size, out_signature, out_signature_size);
JS_FreeValue(context, reordered);
if (result)
{
@ -1220,8 +1270,7 @@ void tf_ssb_append_message(tf_ssb_t* ssb, JSValue message)
JS_FreeValue(context, jsonval);
char id[sodium_base64_ENCODED_LEN(crypto_hash_sha256_BYTES, sodium_base64_VARIANT_ORIGINAL) + 7 + 1];
tf_ssb_calculate_message_id(ssb->context, root, id, sizeof(id));
if (valid)
if (valid && tf_ssb_verify_and_strip_signature(ssb->context, root, id, sizeof(id), NULL, 0, NULL))
{
if (tf_ssb_db_store_message(ssb, ssb->context, id, root, signature_base64, false))
{
@ -1232,8 +1281,7 @@ void tf_ssb_append_message(tf_ssb_t* ssb, JSValue message)
printf("message not stored.\n");
}
}
if (!tf_ssb_verify_and_strip_signature(ssb->context, root, NULL, 0, NULL))
else
{
printf("Failed to verify message signature.\n");
}