From 0117704858d6b9ca2ff9151e474d2a7754e80042 Mon Sep 17 00:00:00 2001 From: Lorenzo Delgado Date: Wed, 22 Feb 2023 17:33:38 +0100 Subject: [PATCH] fix(jsonrpc): use padded-base64 for payload encoding --- tests/common/test_base64_codec.nim | 40 +++++++++++++++++++ .../wakunode_jsonrpc/test_jsonrpc_relay.nim | 8 ++-- tests/v2/wakunode_rest/test_rest_relay.nim | 6 +-- .../wakunode_rest/test_rest_relay_serdes.nim | 6 +-- waku/common/base64.nim | 33 ++++++++++----- waku/v2/node/jsonrpc/message.nim | 2 +- waku/v2/node/jsonrpc/relay/handlers.nim | 2 +- waku/v2/node/rest/base64.nim | 5 --- waku/v2/node/rest/relay/types.nim | 6 +-- 9 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 tests/common/test_base64_codec.nim delete mode 100644 waku/v2/node/rest/base64.nim diff --git a/tests/common/test_base64_codec.nim b/tests/common/test_base64_codec.nim new file mode 100644 index 0000000000..cfc404ab25 --- /dev/null +++ b/tests/common/test_base64_codec.nim @@ -0,0 +1,40 @@ + +{.used.} + +import + stew/[results, byteutils], + testutils/unittests +import + ../../waku/common/base64 + + +suite "Waku Common - stew base64 wrapper": + + test "encode into base64 (with padding)": + ## Given + # From RFC 4648 test vectors: https://www.rfc-editor.org/rfc/rfc4648#page-12 + let data = "fooba" + + ## When + let encoded = base64.encode(data) + + ## Then + check: + encoded == Base64String("Zm9vYmE=") + + + test "decode from base64 (with padding)": + ## Given + # From RFC 4648 test vectors: https://www.rfc-editor.org/rfc/rfc4648#page-12 + let data = Base64String("Zm9vYg==") + + ## When + let decodedRes = base64.decode(data) + + ## Then + check: + decodedRes.isOk() + + let decoded = decodedRes.tryGet() + check: + decoded == toBytes("foob") diff --git a/tests/v2/wakunode_jsonrpc/test_jsonrpc_relay.nim b/tests/v2/wakunode_jsonrpc/test_jsonrpc_relay.nim index e00b9f4123..0ce7ce265b 100644 --- a/tests/v2/wakunode_jsonrpc/test_jsonrpc_relay.nim +++ b/tests/v2/wakunode_jsonrpc/test_jsonrpc_relay.nim @@ -127,7 +127,7 @@ suite "Waku v2 JSON-RPC API - Relay": ## When let rpcMessage = WakuMessageRPC( - payload: Base64String.encode(message.payload), + payload: base64.encode(message.payload), contentTopic: some(message.contentTopic), timestamp: some(message.timestamp), version: some(message.version) @@ -201,7 +201,7 @@ suite "Waku v2 JSON-RPC API - Relay": ## Then check: dstMessages.len == 4 - dstMessages[2].payload == Base64String.encode(messages[2].payload) + dstMessages[2].payload == base64.encode(messages[2].payload) dstMessages[2].contentTopic.get() == messages[2].contentTopic dstMessages[2].timestamp.get() == messages[2].timestamp dstMessages[2].version.get() == messages[2].version @@ -264,7 +264,7 @@ suite "Waku v2 JSON-RPC API - Relay (Private)": ## Given let payload = @[byte 38] - payloadBase64 = Base64String.encode(payload) + payloadBase64 = base64.encode(payload) let message = WakuMessageRPC( payload: payloadBase64, @@ -353,7 +353,7 @@ suite "Waku v2 JSON-RPC API - Relay (Private)": ## Given let payload = @[byte 38] - payloadBase64 = Base64String.encode(payload) + payloadBase64 = base64.encode(payload) let message = WakuMessageRPC( payload: payloadBase64, diff --git a/tests/v2/wakunode_rest/test_rest_relay.nim b/tests/v2/wakunode_rest/test_rest_relay.nim index d8e519a5fa..a949e0f730 100644 --- a/tests/v2/wakunode_rest/test_rest_relay.nim +++ b/tests/v2/wakunode_rest/test_rest_relay.nim @@ -8,10 +8,10 @@ import presto, presto/client as presto_client, libp2p/crypto/crypto import + ../../waku/common/base64, ../../waku/v2/node/waku_node, ../../waku/v2/node/rest/server, ../../waku/v2/node/rest/client, - ../../waku/v2/node/rest/base64, ../../waku/v2/node/rest/responses, ../../waku/v2/node/rest/relay/types, ../../waku/v2/node/rest/relay/handlers as relay_api, @@ -163,7 +163,7 @@ suite "Waku v2 Rest API - Relay": $response.contentType == $MIMETYPE_JSON response.data.len == 3 response.data.all do (msg: RelayWakuMessage) -> bool: - msg.payload == Base64String.encode("TEST-1") and + msg.payload == base64.encode("TEST-1") and msg.contentTopic.get().string == "content-topic-x" and msg.version.get() == 2 and msg.timestamp.get() != Timestamp(0) @@ -210,7 +210,7 @@ suite "Waku v2 Rest API - Relay": discard await client.relayPostSubscriptionsV1(newTopics) let response = await client.relayPostMessagesV1(DefaultPubsubTopic, RelayWakuMessage( - payload: Base64String.encode("TEST-PAYLOAD"), + payload: base64.encode("TEST-PAYLOAD"), contentTopic: some(DefaultContentTopic), timestamp: some(int64(2022)) )) diff --git a/tests/v2/wakunode_rest/test_rest_relay_serdes.nim b/tests/v2/wakunode_rest/test_rest_relay_serdes.nim index 6e273bcad0..f656f1f7f4 100644 --- a/tests/v2/wakunode_rest/test_rest_relay_serdes.nim +++ b/tests/v2/wakunode_rest/test_rest_relay_serdes.nim @@ -6,8 +6,8 @@ import unittest2, json_serialization import + ../../waku/common/base64, ../../waku/v2/node/rest/serdes, - ../../waku/v2/node/rest/base64, ../../waku/v2/node/rest/relay/types, ../../waku/v2/protocol/waku_message @@ -18,7 +18,7 @@ suite "Waku v2 Rest API - Relay - serialization": suite "RelayWakuMessage - decode": test "optional fields are not provided": # Given - let payload = Base64String.encode("MESSAGE") + let payload = base64.encode("MESSAGE") let jsonBytes = toBytes("{\"payload\":\"" & $payload & "\"}") # When @@ -36,7 +36,7 @@ suite "Waku v2 Rest API - Relay - serialization": suite "RelayWakuMessage - encode": test "optional fields are none": # Given - let payload = Base64String.encode("MESSAGE") + let payload = base64.encode("MESSAGE") let data = RelayWakuMessage( payload: payload, contentTopic: none(ContentTopic), diff --git a/waku/common/base64.nim b/waku/common/base64.nim index c0f5b0a2ef..9b0469884f 100644 --- a/waku/common/base64.nim +++ b/waku/common/base64.nim @@ -9,19 +9,30 @@ import stew/[results, byteutils, base64] type Base64String* = distinct string -proc encode*(t: type Base64String, value: string|seq[byte]): Base64String = - let val = block: - when value is string: - toBytes(value) - else: - value - Base64String(base64.encode(Base64, val)) +proc encode*[T: byte|char](value: openArray[T]): Base64String = + Base64String(encode(Base64Pad, value)) + +proc encode*(value: string): Base64String = + encode(toBytes(value)) + + +proc decode[T: byte|char](btype: typedesc[Base64Types], + instr: openArray[T]): Result[seq[byte], string] = + ## Decode BASE64 string ``instr`` and return sequence of bytes as result. + if len(instr) == 0: + return ok(newSeq[byte]()) + + var bufferLen = decodedLength(btype, len(instr)) + var buffer = newSeq[byte](bufferLen) + + if decode(btype, instr, buffer, bufferLen) != Base64Status.Success: + return err("Incorrect base64 string") + + buffer.setLen(bufferLen) + ok(buffer) proc decode*(t: Base64String): Result[seq[byte], string] = - try: - ok(base64.decode(Base64, string(t))) - except: - err("decoding failed: " & getCurrentExceptionMsg()) + decode(Base64Pad, string(t)) proc `$`*(t: Base64String): string {.inline.}= diff --git a/waku/v2/node/jsonrpc/message.nim b/waku/v2/node/jsonrpc/message.nim index 66a862526d..9202aea8cb 100644 --- a/waku/v2/node/jsonrpc/message.nim +++ b/waku/v2/node/jsonrpc/message.nim @@ -21,7 +21,7 @@ type func toWakuMessageRPC*(msg: WakuMessage): WakuMessageRPC = WakuMessageRPC( - payload: Base64String.encode(msg.payload), + payload: base64.encode(msg.payload), contentTopic: some(msg.contentTopic), version: some(msg.version), timestamp: some(msg.timestamp), diff --git a/waku/v2/node/jsonrpc/relay/handlers.nim b/waku/v2/node/jsonrpc/relay/handlers.nim index 64d4a05460..11b843c580 100644 --- a/waku/v2/node/jsonrpc/relay/handlers.nim +++ b/waku/v2/node/jsonrpc/relay/handlers.nim @@ -128,7 +128,7 @@ proc toWakuMessageRPC(message: WakuMessage, keyInfo = keyInfo(symkey, privateKey) decoded = decodePayload(message, keyInfo) - WakuMessageRPC(payload: Base64String.encode(decoded.get().payload), + WakuMessageRPC(payload: base64.encode(decoded.get().payload), contentTopic: some(message.contentTopic), version: some(message.version), timestamp: some(message.timestamp)) diff --git a/waku/v2/node/rest/base64.nim b/waku/v2/node/rest/base64.nim deleted file mode 100644 index 77884bac9a..0000000000 --- a/waku/v2/node/rest/base64.nim +++ /dev/null @@ -1,5 +0,0 @@ -{.deprecated: "import 'waku/common/base64' instead".} - -import ../../../common/base64 - -export base64 diff --git a/waku/v2/node/rest/relay/types.nim b/waku/v2/node/rest/relay/types.nim index 9355f13167..1e976f2e77 100644 --- a/waku/v2/node/rest/relay/types.nim +++ b/waku/v2/node/rest/relay/types.nim @@ -10,9 +10,9 @@ import json_serialization/std/options, presto/[route, client, common] import + ../../../../common/base64, ../../../protocol/waku_message, - ../serdes, - ../base64 + ../serdes #### Types @@ -37,7 +37,7 @@ type proc toRelayWakuMessage*(msg: WakuMessage): RelayWakuMessage = RelayWakuMessage( - payload: base64.encode(Base64String, msg.payload), + payload: base64.encode(msg.payload), contentTopic: some(msg.contentTopic), version: some(Natural(msg.version)), timestamp: some(msg.timestamp)