forked from cory/tildefriends
Make ssb.privateMessageDecrypt do its work not on the main thread. I think that's finally everything for real.
This commit is contained in:
parent
3ee2c00726
commit
b16c37e48b
93
src/ssb.js.c
93
src/ssb.js.c
@ -2046,25 +2046,31 @@ static JSValue _tf_ssb_private_message_encrypt(JSContext* context, JSValueConst
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
typedef struct _private_message_decrypt_t
|
||||||
{
|
{
|
||||||
JSValue result = JS_UNDEFINED;
|
const char* user;
|
||||||
const char* user = JS_ToCString(context, argv[0]);
|
const char* identity;
|
||||||
const char* identity = JS_ToCString(context, argv[1]);
|
size_t message_size;
|
||||||
size_t message_size = 0;
|
const char* message;
|
||||||
const char* message = JS_ToCStringLen(context, &message_size, argv[2]);
|
const char* decrypted;
|
||||||
|
size_t decrypted_size;
|
||||||
|
const char* error;
|
||||||
|
JSValue promise[2];
|
||||||
|
} private_message_decrypt_t;
|
||||||
|
|
||||||
|
static void _tf_ssb_private_message_decrypt_work(tf_ssb_t* ssb, void* user_data)
|
||||||
|
{
|
||||||
|
private_message_decrypt_t* work = user_data;
|
||||||
|
|
||||||
uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
|
uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
|
||||||
|
|
||||||
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
bool found = _tf_ssb_get_private_key_curve25519(db, user, identity, private_key);
|
bool found = _tf_ssb_get_private_key_curve25519(db, work->user, work->identity, private_key);
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
uint8_t* decoded = tf_malloc(message_size);
|
uint8_t* decoded = tf_malloc(work->message_size);
|
||||||
int decoded_length = tf_base64_decode(message, message_size - strlen(".box"), decoded, message_size);
|
int decoded_length = tf_base64_decode(work->message, work->message_size - strlen(".box"), decoded, work->message_size);
|
||||||
uint8_t* nonce = decoded;
|
uint8_t* nonce = decoded;
|
||||||
uint8_t* public_key = decoded + crypto_box_NONCEBYTES;
|
uint8_t* public_key = decoded + crypto_box_NONCEBYTES;
|
||||||
if (public_key + crypto_secretbox_KEYBYTES < decoded + decoded_length)
|
if (public_key + crypto_secretbox_KEYBYTES < decoded + decoded_length)
|
||||||
@ -2090,36 +2096,83 @@ static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst
|
|||||||
uint8_t* key = out + 1;
|
uint8_t* key = out + 1;
|
||||||
if (crypto_secretbox_open_easy(decrypted, body, body_size, nonce, key) != -1)
|
if (crypto_secretbox_open_easy(decrypted, body, body_size, nonce, key) != -1)
|
||||||
{
|
{
|
||||||
result = JS_NewStringLen(context, (const char*)decrypted, body_size - crypto_secretbox_MACBYTES);
|
work->decrypted = (const char*)decrypted;
|
||||||
|
work->decrypted_size = body_size - crypto_secretbox_MACBYTES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = JS_ThrowInternalError(context, "Received key to open secret box containing message body, but it did not work.");
|
work->error = "Received key to open secret box containing message body, but it did not work.";
|
||||||
}
|
}
|
||||||
tf_free(decrypted);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = JS_ThrowInternalError(context, "crypto_scalarmult failed.");
|
work->error = "crypto_scalarmult failed.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = JS_ThrowInternalError(context, "Encrypted message was not long enough to contains its one-time public key.");
|
work->error = "Encrypted message was not long enough to contains its one-time public key.";
|
||||||
}
|
}
|
||||||
tf_free(decoded);
|
tf_free(decoded);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = JS_ThrowInternalError(context, "Private key not found for user %s with id %s.", user, identity);
|
work->error = "Private key not found for user.";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JS_FreeCString(context, user);
|
static void _tf_ssb_private_message_decrypt_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||||
JS_FreeCString(context, identity);
|
{
|
||||||
JS_FreeCString(context, message);
|
private_message_decrypt_t* work = user_data;
|
||||||
|
JSContext* context = tf_ssb_get_context(ssb);
|
||||||
|
JSValue error = JS_UNDEFINED;
|
||||||
|
if (work->error)
|
||||||
|
{
|
||||||
|
JSValue result = JS_ThrowInternalError(context, "%s", work->error);
|
||||||
|
error = JS_Call(context, work->promise[1], JS_UNDEFINED, 1, &result);
|
||||||
|
JS_FreeValue(context, result);
|
||||||
|
}
|
||||||
|
else if (work->decrypted)
|
||||||
|
{
|
||||||
|
JSValue result = JS_NewStringLen(context, work->decrypted, work->decrypted_size);
|
||||||
|
error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result);
|
||||||
|
JS_FreeValue(context, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSValue result = JS_UNDEFINED;
|
||||||
|
error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result);
|
||||||
|
}
|
||||||
|
tf_util_report_error(context, error);
|
||||||
|
JS_FreeValue(context, error);
|
||||||
|
JS_FreeValue(context, work->promise[0]);
|
||||||
|
JS_FreeValue(context, work->promise[1]);
|
||||||
|
JS_FreeCString(context, work->user);
|
||||||
|
JS_FreeCString(context, work->identity);
|
||||||
|
JS_FreeCString(context, work->message);
|
||||||
|
tf_free((void*)work->decrypted);
|
||||||
|
tf_free(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
|
||||||
|
const char* user = JS_ToCString(context, argv[0]);
|
||||||
|
const char* identity = JS_ToCString(context, argv[1]);
|
||||||
|
size_t message_size = 0;
|
||||||
|
const char* message = JS_ToCStringLen(context, &message_size, argv[2]);
|
||||||
|
|
||||||
|
private_message_decrypt_t* work = tf_malloc(sizeof(private_message_decrypt_t));
|
||||||
|
*work = (private_message_decrypt_t) {
|
||||||
|
.user = user,
|
||||||
|
.identity = identity,
|
||||||
|
.message_size = message_size,
|
||||||
|
.message = message,
|
||||||
|
};
|
||||||
|
JSValue result = JS_NewPromiseCapability(context, work->promise);
|
||||||
|
tf_ssb_run_work(ssb, _tf_ssb_private_message_decrypt_work, _tf_ssb_private_message_decrypt_after_work, work);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,10 +847,11 @@ void tf_ssb_test_encrypt(const tf_test_options_t* options)
|
|||||||
"async function main() {\n"
|
"async function main() {\n"
|
||||||
" let a = await ssb.createIdentity('test');\n"
|
" let a = await ssb.createIdentity('test');\n"
|
||||||
" let b = await ssb.createIdentity('test');\n"
|
" let b = await ssb.createIdentity('test');\n"
|
||||||
" let c = await ssb.privateMessageEncrypt('test', a, [a, b], {'foo': 1});\n"
|
" let c = await ssb.privateMessageEncrypt('test', a, [a, b], \"{'foo': 1}\");\n"
|
||||||
" if (!c.endsWith('.box')) {\n"
|
" if (!c.endsWith('.box')) {\n"
|
||||||
" exit(1);\n"
|
" exit(1);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
|
" print(await ssb.privateMessageDecrypt('test', a, c));\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"main().catch(() => exit(2));\n");
|
"main().catch(() => exit(2));\n");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user