diff --git a/src/lib/crypto.ts b/src/lib/crypto.ts index af21699d7f..321574606d 100644 --- a/src/lib/crypto.ts +++ b/src/lib/crypto.ts @@ -2,8 +2,8 @@ import nodeCrypto from "crypto"; import * as secp from "@noble/secp256k1"; import sha3 from "js-sha3"; -import { concat } from "uint8arrays/concat"; +import { concat } from "./utils"; import { Asymmetric, Symmetric } from "./waku_message/constants"; declare const self: Record | undefined; @@ -65,7 +65,10 @@ export async function sign( recovered: true, der: false, }); - return concat([signature, [recoveryId]], signature.length + 1); + return concat( + [signature, new Uint8Array([recoveryId])], + signature.length + 1 + ); } export function keccak256(input: Uint8Array): Uint8Array { @@ -74,7 +77,7 @@ export function keccak256(input: Uint8Array): Uint8Array { export function compressPublicKey(publicKey: Uint8Array): Uint8Array { if (publicKey.length === 64) { - publicKey = concat([[4], publicKey], 65); + publicKey = concat([new Uint8Array([4]), publicKey], 65); } const point = secp.Point.fromHex(publicKey); return point.toRawBytes(true); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 2d0ca74b11..6b9f0f343a 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -29,3 +29,22 @@ export const bytesToUtf8 = (b: Uint8Array): string => toString(b, "utf8"); * Encode utf-8 string to byte array. */ export const utf8ToBytes = (s: string): Uint8Array => fromString(s, "utf8"); + +/** + * Concatenate using Uint8Arrays as `Buffer` has a different behavior with `DataView` + */ +export function concat( + byteArrays: Uint8Array[], + totalLength?: number +): Uint8Array { + const len = + totalLength ?? byteArrays.reduce((acc, curr) => acc + curr.length, 0); + const res = new Uint8Array(len); + + let offset = 0; + for (const bytes of byteArrays) { + res.set(bytes, offset); + offset += bytes.length; + } + return res; +} diff --git a/src/lib/waku_light_push/index.ts b/src/lib/waku_light_push/index.ts index b4fdf4fe35..2db473d525 100644 --- a/src/lib/waku_light_push/index.ts +++ b/src/lib/waku_light_push/index.ts @@ -4,11 +4,11 @@ import all from "it-all"; import * as lp from "it-length-prefixed"; import { pipe } from "it-pipe"; import { Libp2p } from "libp2p"; -import { concat } from "uint8arrays/concat"; import { PushResponse } from "../../proto/light_push"; import { DefaultPubSubTopic } from "../constants"; import { getPeersForProtocol, selectRandomPeer } from "../select_peer"; +import { concat } from "../utils"; import { WakuMessage } from "../waku_message"; import { PushRPC } from "./push_rpc"; diff --git a/src/lib/waku_message/ecies.ts b/src/lib/waku_message/ecies.ts index e05ac121df..eed121cc31 100644 --- a/src/lib/waku_message/ecies.ts +++ b/src/lib/waku_message/ecies.ts @@ -1,8 +1,7 @@ import * as secp from "@noble/secp256k1"; -import { concat } from "uint8arrays/concat"; import { getSubtle, randomBytes, sha256 } from "../crypto"; -import { hexToBytes } from "../utils"; +import { concat, hexToBytes } from "../utils"; /** * HKDF as implemented in go-ethereum. */ diff --git a/src/lib/waku_message/version_1.spec.ts b/src/lib/waku_message/version_1.spec.ts index 7351895a0b..89e937dbf6 100644 --- a/src/lib/waku_message/version_1.spec.ts +++ b/src/lib/waku_message/version_1.spec.ts @@ -2,6 +2,7 @@ import { expect } from "chai"; import fc from "fast-check"; import { getPublicKey } from "../crypto"; +import { bytesToHex } from "../utils"; import { clearDecode, @@ -72,4 +73,15 @@ describe("Waku Message Version 1", function () { ) ); }); + + it("Clear encode and decode", async function () { + await fc.assert( + fc.asyncProperty(fc.uint8Array(), async (payload) => { + const enc = await clearEncode(payload); + const dec = clearDecode(enc.payload); + if (!dec?.payload) throw "payload missing"; + expect(bytesToHex(dec?.payload)).to.eq(bytesToHex(payload)); + }) + ); + }); }); diff --git a/src/lib/waku_message/version_1.ts b/src/lib/waku_message/version_1.ts index 886d011c4f..56b39ad795 100644 --- a/src/lib/waku_message/version_1.ts +++ b/src/lib/waku_message/version_1.ts @@ -1,8 +1,7 @@ import * as secp from "@noble/secp256k1"; -import { concat } from "uint8arrays/concat"; import { keccak256, randomBytes, sign } from "../crypto"; -import { hexToBytes } from "../utils"; +import { concat, hexToBytes } from "../utils"; import { Symmetric } from "./constants"; import * as ecies from "./ecies"; @@ -55,7 +54,6 @@ export async function clearEncode( } envelope = concat([envelope, pad]); - let sig; if (sigPrivKey) { envelope[0] |= IsSignedMask; diff --git a/src/lib/waku_store/index.ts b/src/lib/waku_store/index.ts index 317097aa55..3b88e4f97b 100644 --- a/src/lib/waku_store/index.ts +++ b/src/lib/waku_store/index.ts @@ -5,13 +5,12 @@ import all from "it-all"; import * as lp from "it-length-prefixed"; import { pipe } from "it-pipe"; import { Libp2p } from "libp2p"; -import { concat } from "uint8arrays/concat"; import * as protoV2Beta4 from "../../proto/store_v2beta4"; import { HistoryResponse } from "../../proto/store_v2beta4"; import { DefaultPubSubTopic, StoreCodecs } from "../constants"; import { getPeersForProtocol, selectRandomPeer } from "../select_peer"; -import { hexToBytes } from "../utils"; +import { concat, hexToBytes } from "../utils"; import { DecryptionMethod, WakuMessage } from "../waku_message"; import { HistoryRPC, PageDirection } from "./history_rpc";