waku-org / js-waku

JavaScript implementation of Waku v2
https://js.waku.org
Apache License 2.0
168 stars 42 forks source link

Encrypted encoder/decoder does not work well if symKey length is not 32 bytes #1699

Open agazso opened 11 months ago

agazso commented 11 months ago

This is a bug report

Problem

I use the symmetric encrypted encoder/decoder from the @waku/message-encryption package.

If the key length is different than 32 bytes then no data will be stored with lightPush.send.

If the key length is different than 32 bytes when using store.queryGenerator then the returned generator from the is empty and cannot be iterated if there is no data found under the topic or DecodedMessage returned from a query is undefined if there is data found under the topic.

Proposed Solutions

I think the best would be to check in the createEncoder and createDecoder if the symKey length is exactly 32 bytes long.

Notes

Example code:

import { Protocols } from '@waku/interfaces'
import { createLightNode, waitForRemotePeer } from '@waku/sdk'
import { multiaddr } from '@multiformats/multiaddr'
import {
    createDecoder,
    createEncoder,
  } from "@waku/message-encryption/symmetric";
import { hexToBytes } from '@waku/utils/bytes'

const encryptionKey = 'aaaf10b0c32d3ed6c509e640c38a04b31b1b0caadec4e4e6c7cf04b404dec4b427'

// change the id of the peer
const peerMultiaddr = multiaddr(
    '/ip4/127.0.0.1/tcp/8000/ws/p2p/16Uiu2HAm53sojJN72rFbYg6GV2LpRRER9XeWkiEAhjKy3aL9cN5Z',
)

main()

async function main() {
    if (process.argv[2] === 'send') {
        await send()
        return
    }
    const waku = await createLightNode({})
    await waku.start()
    await waku.dial(peerMultiaddr)
    await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush, Protocols.Store])

    const symKey = hexToBytes(encryptionKey)
    const messageDecoder = createDecoder(encryptionKey, symKey)

    const results = await waku.store.queryGenerator([messageDecoder])

    for await (const messagePromises of results) {
        for (const messagePromise of messagePromises) {
            const message = await messagePromise
            console.debug({ message })
        }
    }

    process.exit()
}

async function send() {
    const waku = await createLightNode({})
    await waku.start()
    await waku.dial(peerMultiaddr)
    await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush, Protocols.Store])

    const symKey = hexToBytes(encryptionKey)
    const encoder = createEncoder({ contentTopic: encryptionKey, symKey })
    await waku.lightPush.send(encoder, { payload: new TextEncoder().encode('hello') })

    process.exit()
}
fryorcraken commented 11 months ago

Agreed, check should be done on key size and probably error throw or returned if not 32 bytes.