Make ssb.privateMessageDecrypt do its work not on the main thread. I think that's finally everything for real.
This commit is contained in:
		
							
								
								
									
										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"); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user