diff --git a/core/auth.js b/core/auth.js index 5aa61d3d..49fcfa13 100644 --- a/core/auth.js +++ b/core/auth.js @@ -45,12 +45,12 @@ function readSession(session) { let jwt_parts = session?.split('.'); if (jwt_parts?.length === 3) { let [header, payload, signature] = jwt_parts; - header = JSON.parse(base64Decode(unb64url(header))); + header = JSON.parse(utf8Decode(base64Decode(unb64url(header)))); if (header.typ === 'JWT' && header.alg === 'HS256') { signature = unb64url(signature); let id = ssb.getIdentities(':auth'); if (id?.length && ssb.hmacsha256verify(id[0], payload, signature)) { - let result = JSON.parse(base64Decode(unb64url(payload))); + let result = JSON.parse(utf8Decode(base64Decode(unb64url(payload)))); let now = new Date().valueOf() if (now < result.exp) { print(`JWT valid for another ${(result.exp - now) / 1000} seconds.`); diff --git a/src/tests.c b/src/tests.c index f485476d..bc9e4063 100644 --- a/src/tests.c +++ b/src/tests.c @@ -653,7 +653,7 @@ static void _test_b64(const tf_test_options_t* options) fprintf(file, "'use strict';\n" "print(base64Encode('hello'));\n" - "let x = base64Decode(base64Encode('hello'));\n" + "let x = utf8Decode(base64Decode(base64Encode('hello')));\n" "if (x !== 'hello') {\n" " print(x);\n" " exit(1);\n" diff --git a/src/util.js.c b/src/util.js.c index ec749163..607d35d9 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -1,5 +1,6 @@ #include "util.js.h" +#include "bip39.h" #include "log.h" #include "mem.h" #include "task.h" @@ -71,8 +72,20 @@ JSValue tf_util_utf8_decode(JSContext* context, JSValue value) static JSValue _util_base64_encode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { JSValue result = JS_UNDEFINED; + JSValue buffer = JS_UNDEFINED; size_t length = 0; uint8_t* array = tf_util_try_get_array_buffer(context, &length, argv[0]); + if (!array) + { + size_t offset; + size_t element_size; + buffer = tf_util_try_get_typed_array_buffer(context, argv[0], &offset, &length, &element_size); + if (!JS_IsException(buffer)) + { + array = tf_util_try_get_array_buffer(context, &length, buffer); + } + } + if (array) { char* encoded = tf_malloc(length * 4); @@ -95,6 +108,7 @@ static JSValue _util_base64_encode(JSContext* context, JSValueConst this_val, in tf_free(encoded); JS_FreeCString(context, value); } + JS_FreeValue(context, buffer); return result; } @@ -103,19 +117,58 @@ static JSValue _util_base64_decode(JSContext* context, JSValueConst this_val, in JSValue result = JS_UNDEFINED; size_t length = 0; const char* value = JS_ToCStringLen(context, &length, argv[0]); - uint8_t* encoded = tf_malloc(length); + uint8_t* decoded = tf_malloc(length); - int r = tf_base64_decode(value, length, encoded, length); + int r = tf_base64_decode(value, length, decoded, length); if (r >= 0) { - result = JS_NewStringLen(context, (const char*)encoded, r); + result = tf_util_new_uint8_array(context, decoded, r); } - tf_free(encoded); + tf_free(decoded); JS_FreeCString(context, value); return result; } +static JSValue _util_bip39_words(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + JSValue result = JS_UNDEFINED; + JSValue buffer = JS_UNDEFINED; + size_t length; + uint8_t* array = tf_util_try_get_array_buffer(context, &length, argv[0]); + if (!array) + { + size_t offset; + size_t element_size; + buffer = tf_util_try_get_typed_array_buffer(context, argv[0], &offset, &length, &element_size); + if (!JS_IsException(buffer)) + { + array = tf_util_try_get_array_buffer(context, &length, buffer); + } + } + + char words[2048] = ""; + if (array && tf_bip39_bytes_to_words(array, length, words, sizeof(words))) + { + result = JS_NewString(context, words); + } + JS_FreeValue(context, buffer); + return result; +} + +static JSValue _util_bip39_bytes(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + const char* words = JS_ToCString(context, argv[0]); + uint8_t bytes[33] = { 0 }; + bool success = tf_bip39_words_to_bytes(words, bytes, sizeof(bytes)); + JS_FreeCString(context, words); + if (success) + { + return tf_util_new_uint8_array(context, bytes, sizeof(bytes)); + } + return JS_UNDEFINED; +} + uint8_t* tf_util_try_get_array_buffer(JSContext* context, size_t* psize, JSValueConst obj) { uint8_t* result = JS_GetArrayBuffer(context, psize, obj); @@ -434,6 +487,8 @@ void tf_util_register(JSContext* context) JS_SetPropertyStr(context, global, "utf8Encode", JS_NewCFunction(context, _util_utf8_encode, "utf8Encode", 1)); JS_SetPropertyStr(context, global, "base64Decode", JS_NewCFunction(context, _util_base64_decode, "base64Decode", 1)); JS_SetPropertyStr(context, global, "base64Encode", JS_NewCFunction(context, _util_base64_encode, "base64Encode", 1)); + JS_SetPropertyStr(context, global, "bip39Words", JS_NewCFunction(context, _util_bip39_words, "bip39Words", 1)); + JS_SetPropertyStr(context, global, "bip39Bytes", JS_NewCFunction(context, _util_bip39_bytes, "bip39Bytes", 1)); JS_SetPropertyStr(context, global, "print", JS_NewCFunction(context, _util_print, "print", 1)); JS_SetPropertyStr(context, global, "setTimeout", JS_NewCFunction(context, _util_setTimeout, "setTimeout", 2)); JS_SetPropertyStr(context, global, "parseHttpRequest", JS_NewCFunction(context, _util_parseHttpRequest, "parseHttpRequest", 2));