refactor(utils): moved noise/compat payload encryption code to utils

This commit is contained in:
Lorenzo Delgado 2023-02-07 10:45:25 +01:00 committed by GitHub
parent fd433ce0e2
commit 0826bdad99
13 changed files with 220 additions and 207 deletions

View File

@ -27,17 +27,21 @@ import
../../waku/v2/protocol/waku_lightpush/rpc, ../../waku/v2/protocol/waku_lightpush/rpc,
../../waku/v2/protocol/waku_filter, ../../waku/v2/protocol/waku_filter,
../../waku/v2/protocol/waku_store, ../../waku/v2/protocol/waku_store,
../../waku/v2/node/[waku_node, waku_payload, waku_metrics], ../../waku/v2/node/waku_node,
../../waku/v2/node/waku_metrics,
../../waku/v2/node/dnsdisc/waku_dnsdisc, ../../waku/v2/node/dnsdisc/waku_dnsdisc,
../../waku/v2/node/peer_manager, ../../waku/v2/node/peer_manager,
../../waku/v2/utils/[peers, time], ../../waku/v2/utils/compat,
../../waku/v2/utils/peers,
../../waku/v2/utils/time,
../../waku/common/utils/nat, ../../waku/common/utils/nat,
./config_chat2 ./config_chat2
when defined(rln): when defined(rln):
import import
libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/rpc/messages,
libp2p/protocols/pubsub/pubsub, libp2p/protocols/pubsub/pubsub
import
../../waku/v2/protocol/waku_rln_relay ../../waku/v2/protocol/waku_rln_relay
const Help = """ const Help = """

View File

@ -4,7 +4,9 @@ import
./v2/test_confutils_envvar, ./v2/test_confutils_envvar,
./v2/test_sqlite_migrations ./v2/test_sqlite_migrations
## Waku archive test suite ## Waku v2
# Waku archive test suite
import import
./v2/waku_archive/test_driver_queue_index, ./v2/waku_archive/test_driver_queue_index,
./v2/waku_archive/test_driver_queue_pagination, ./v2/waku_archive/test_driver_queue_pagination,
@ -15,7 +17,7 @@ import
./v2/waku_archive/test_retention_policy, ./v2/waku_archive/test_retention_policy,
./v2/waku_archive/test_waku_archive ./v2/waku_archive/test_waku_archive
## Waku store test suite # Waku store test suite
import import
./v2/waku_store/test_rpc_codec, ./v2/waku_store/test_rpc_codec,
./v2/waku_store/test_waku_store, ./v2/waku_store/test_waku_store,
@ -38,7 +40,6 @@ import
./v2/test_wakunode_filter, ./v2/test_wakunode_filter,
./v2/test_waku_peer_exchange, ./v2/test_waku_peer_exchange,
./v2/test_peer_store_extended, ./v2/test_peer_store_extended,
./v2/test_waku_payload,
./v2/test_waku_swap, ./v2/test_waku_swap,
./v2/test_utils_peers, ./v2/test_utils_peers,
./v2/test_message_cache, ./v2/test_message_cache,
@ -62,6 +63,7 @@ import
./v2/test_waku_noise_sessions, ./v2/test_waku_noise_sessions,
./v2/test_waku_switch, ./v2/test_waku_switch,
# Utils # Utils
./v2/test_utils_compat,
./v2/test_utils_keyfile ./v2/test_utils_keyfile
@ -74,7 +76,6 @@ when defined(rln):
./v2/test_waku_rln_relay_onchain ./v2/test_waku_rln_relay_onchain
# TODO: Only enable this once swap module is integrated more nicely as a dependency, i.e. as submodule with CI etc # TODO: Only enable this once swap module is integrated more nicely as a dependency, i.e. as submodule with CI etc
# For PoC execute it manually and run separate module here: https://github.com/vacp2p/swap-contracts-module # For PoC execute it manually and run separate module here: https://github.com/vacp2p/swap-contracts-module
# ./v2/test_waku_swap_contracts # ./v2/test_waku_swap_contracts

View File

@ -32,6 +32,7 @@ import
../../waku/v2/protocol/waku_filter, ../../waku/v2/protocol/waku_filter,
../../waku/v2/protocol/waku_filter/rpc, ../../waku/v2/protocol/waku_filter/rpc,
../../waku/v2/protocol/waku_filter/client, ../../waku/v2/protocol/waku_filter/client,
../../waku/v2/utils/compat,
../../waku/v2/utils/peers, ../../waku/v2/utils/peers,
../../waku/v2/utils/time, ../../waku/v2/utils/time,
./testlib/common, ./testlib/common,

View File

@ -1,9 +1,10 @@
{.used.} {.used.}
import import
testutils/unittests, testutils/unittests
import
../../waku/v2/protocol/waku_message, ../../waku/v2/protocol/waku_message,
../../waku/v2/node/waku_payload, ../../waku/v2/utils/compat,
../../waku/v2/utils/time ../../waku/v2/utils/time
procSuite "Waku Payload": procSuite "Waku Payload":
@ -120,28 +121,28 @@ procSuite "Waku Payload":
payload = @[byte 0, 1, 2] payload = @[byte 0, 1, 2]
timestamp = Timestamp(10) timestamp = Timestamp(10)
msg = WakuMessage(payload: payload, version: version, timestamp: timestamp) msg = WakuMessage(payload: payload, version: version, timestamp: timestamp)
## When ## When
let pb = msg.encode() let pb = msg.encode()
let msgDecoded = WakuMessage.decode(pb.buffer) let msgDecoded = WakuMessage.decode(pb.buffer)
## Then ## Then
check: check:
msgDecoded.isOk() msgDecoded.isOk()
let timestampDecoded = msgDecoded.value.timestamp let timestampDecoded = msgDecoded.value.timestamp
check: check:
timestampDecoded == timestamp timestampDecoded == timestamp
test "Encode/Decode waku message without timestamp": test "Encode/Decode waku message without timestamp":
## Test the encoding and decoding of a WakuMessage with an empty timestamp field ## Test the encoding and decoding of a WakuMessage with an empty timestamp field
## Given ## Given
let let
version = 0'u32 version = 0'u32
payload = @[byte 0, 1, 2] payload = @[byte 0, 1, 2]
msg = WakuMessage(payload: payload, version: version) msg = WakuMessage(payload: payload, version: version)
## When ## When
let pb = msg.encode() let pb = msg.encode()
let msgDecoded = WakuMessage.decode(pb.buffer) let msgDecoded = WakuMessage.decode(pb.buffer)
@ -149,7 +150,7 @@ procSuite "Waku Payload":
## Then ## Then
check: check:
msgDecoded.isOk() msgDecoded.isOk()
let timestampDecoded = msgDecoded.value.timestamp let timestampDecoded = msgDecoded.value.timestamp
check: check:
timestampDecoded == Timestamp(0) timestampDecoded == Timestamp(0)

View File

@ -18,7 +18,8 @@ import
import import
../../waku/v1/protocol/waku_protocol, ../../waku/v1/protocol/waku_protocol,
../../waku/v2/protocol/waku_message, ../../waku/v2/protocol/waku_message,
../../waku/v2/node/[waku_node, waku_payload], ../../waku/v2/node/waku_node,
../../waku/v2/utils/compat,
../../waku/v2/utils/peers, ../../waku/v2/utils/peers,
../../apps/wakubridge/wakubridge, ../../apps/wakubridge/wakubridge,
../test_helpers ../test_helpers

View File

@ -5,7 +5,7 @@ import
std/random, std/random,
std/tables, std/tables,
stew/byteutils, stew/byteutils,
../../waku/v2/node/waku_payload, ../../waku/v2/utils/noise as waku_message_utils,
../../waku/v2/protocol/waku_noise/noise_types, ../../waku/v2/protocol/waku_noise/noise_types,
../../waku/v2/protocol/waku_noise/noise_utils, ../../waku/v2/protocol/waku_noise/noise_utils,
../../waku/v2/protocol/waku_noise/noise, ../../waku/v2/protocol/waku_noise/noise,
@ -18,7 +18,7 @@ import
procSuite "Waku Noise": procSuite "Waku Noise":
# We initialize the RNG in test_helpers # We initialize the RNG in test_helpers
let rng = rng() let rng = rng()
# We initialize the RNG in std/random # We initialize the RNG in std/random
@ -29,7 +29,7 @@ procSuite "Waku Noise":
# We test padding for different message lengths # We test padding for different message lengths
let maxMessageLength = 3 * NoisePaddingBlockSize let maxMessageLength = 3 * NoisePaddingBlockSize
for messageLen in 0..maxMessageLength: for messageLen in 0..maxMessageLength:
let let
message = randomSeqByte(rng[], messageLen) message = randomSeqByte(rng[], messageLen)
padded = pkcs7_pad(message, NoisePaddingBlockSize) padded = pkcs7_pad(message, NoisePaddingBlockSize)
@ -50,7 +50,7 @@ procSuite "Waku Noise":
ciphertext: ChaChaPolyCiphertext = encrypt(cipherState, plaintext) ciphertext: ChaChaPolyCiphertext = encrypt(cipherState, plaintext)
decryptedCiphertext: seq[byte] = decrypt(cipherState, ciphertext) decryptedCiphertext: seq[byte] = decrypt(cipherState, ciphertext)
check: check:
plaintext == decryptedCiphertext plaintext == decryptedCiphertext
test "ChaChaPoly Encryption/Decryption: random strings": test "ChaChaPoly Encryption/Decryption: random strings":
@ -66,26 +66,26 @@ procSuite "Waku Noise":
ciphertext: ChaChaPolyCiphertext = encrypt(cipherState, plaintext.toBytes()) ciphertext: ChaChaPolyCiphertext = encrypt(cipherState, plaintext.toBytes())
decryptedCiphertext: seq[byte] = decrypt(cipherState, ciphertext) decryptedCiphertext: seq[byte] = decrypt(cipherState, ciphertext)
check: check:
plaintext.toBytes() == decryptedCiphertext plaintext.toBytes() == decryptedCiphertext
test "Noise public keys: encrypt and decrypt a public key": test "Noise public keys: encrypt and decrypt a public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[]) let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[]) cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey) encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk) decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk)
check: check:
noisePublicKey == decryptedPk noisePublicKey == decryptedPk
test "Noise public keys: decrypt an unencrypted public key": test "Noise public keys: decrypt an unencrypted public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[]) let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[]) cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, noisePublicKey) decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, noisePublicKey)
@ -100,7 +100,7 @@ procSuite "Waku Noise":
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[]) cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey) encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
encryptedPk2: NoisePublicKey = encryptNoisePublicKey(cs, encryptedPk) encryptedPk2: NoisePublicKey = encryptNoisePublicKey(cs, encryptedPk)
check: check:
encryptedPk == encryptedPk2 encryptedPk == encryptedPk2
@ -114,12 +114,12 @@ procSuite "Waku Noise":
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk) decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk)
decryptedPk2: NoisePublicKey = decryptNoisePublicKey(cs, decryptedPk) decryptedPk2: NoisePublicKey = decryptNoisePublicKey(cs, decryptedPk)
check: check:
decryptedPk == decryptedPk2 decryptedPk == decryptedPk2
test "Noise public keys: serialize and deserialize an unencrypted public key": test "Noise public keys: serialize and deserialize an unencrypted public key":
let let
noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[]) noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(noisePublicKey) serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(noisePublicKey)
deserializedNoisePublicKey: NoisePublicKey = intoNoisePublicKey(serializedNoisePublicKey) deserializedNoisePublicKey: NoisePublicKey = intoNoisePublicKey(serializedNoisePublicKey)
@ -131,7 +131,7 @@ procSuite "Waku Noise":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[]) let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[]) cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey) encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(encryptedPk) serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(encryptedPk)
@ -159,7 +159,7 @@ procSuite "Waku Noise":
test "PayloadV2: Encode/Decode a Waku Message (version 2) to a PayloadV2": test "PayloadV2: Encode/Decode a Waku Message (version 2) to a PayloadV2":
# We encode to a WakuMessage a random PayloadV2 # We encode to a WakuMessage a random PayloadV2
let let
payload2 = randomPayloadV2(rng[]) payload2 = randomPayloadV2(rng[])
@ -173,7 +173,7 @@ procSuite "Waku Noise":
# We decode the WakuMessage from the ProtoBuffer # We decode the WakuMessage from the ProtoBuffer
let msgFromPb = WakuMessage.decode(pb.buffer) let msgFromPb = WakuMessage.decode(pb.buffer)
check: check:
msgFromPb.isOk() msgFromPb.isOk()
@ -202,7 +202,7 @@ procSuite "Waku Noise":
test "Noise State Machine: Cipher State primitives": test "Noise State Machine: Cipher State primitives":
# We generate a random Cipher State, associated data ad and plaintext # We generate a random Cipher State, associated data ad and plaintext
var var
cipherState: CipherState = randomCipherState(rng[]) cipherState: CipherState = randomCipherState(rng[])
nonce: uint64 = uint64(rand(0 .. int.high)) nonce: uint64 = uint64(rand(0 .. int.high))
ad: seq[byte] = randomSeqByte(rng[], rand(1..128)) ad: seq[byte] = randomSeqByte(rng[], rand(1..128))
@ -210,13 +210,13 @@ procSuite "Waku Noise":
# We set the random nonce generated in the cipher state # We set the random nonce generated in the cipher state
setNonce(cipherState, nonce) setNonce(cipherState, nonce)
# We perform encryption # We perform encryption
var ciphertext: seq[byte] = encryptWithAd(cipherState, ad, plaintext) var ciphertext: seq[byte] = encryptWithAd(cipherState, ad, plaintext)
# After any encryption/decryption operation, the Cipher State's nonce increases by 1 # After any encryption/decryption operation, the Cipher State's nonce increases by 1
check: check:
getNonce(cipherState) == nonce + 1 getNonce(cipherState) == nonce + 1
# We set the nonce back to its original value for decryption # We set the nonce back to its original value for decryption
setNonce(cipherState, nonce) setNonce(cipherState, nonce)
@ -226,7 +226,7 @@ procSuite "Waku Noise":
# We check if encryption and decryption are correct and that nonce correctly increased after decryption # We check if encryption and decryption are correct and that nonce correctly increased after decryption
check: check:
getNonce(cipherState) == nonce + 1 getNonce(cipherState) == nonce + 1
plaintext == decrypted plaintext == decrypted
# If a Cipher State has no key set, encryptWithAd should return the plaintext without increasing the nonce # If a Cipher State has no key set, encryptWithAd should return the plaintext without increasing the nonce
@ -254,7 +254,7 @@ procSuite "Waku Noise":
# A Cipher State cannot have a nonce greater or equal 2^64-1 # A Cipher State cannot have a nonce greater or equal 2^64-1
# Note that NonceMax is uint64.high - 1 = 2^64-1-1 and that nonce is increased after each encryption and decryption operation # Note that NonceMax is uint64.high - 1 = 2^64-1-1 and that nonce is increased after each encryption and decryption operation
# We generate a test Cipher State with nonce set to MaxNonce # We generate a test Cipher State with nonce set to MaxNonce
cipherState = randomCipherState(rng[]) cipherState = randomCipherState(rng[])
setNonce(cipherState, NonceMax) setNonce(cipherState, NonceMax)
@ -264,10 +264,10 @@ procSuite "Waku Noise":
for _ in [1..5]: for _ in [1..5]:
expect NoiseNonceMaxError: expect NoiseNonceMaxError:
ciphertext = encryptWithAd(cipherState, ad, plaintext) ciphertext = encryptWithAd(cipherState, ad, plaintext)
check: check:
getNonce(cipherState) == NonceMax + 1 getNonce(cipherState) == NonceMax + 1
# We generate a test Cipher State # We generate a test Cipher State
# Since nonce is increased after decryption as well, we need to generate a proper ciphertext in order to test MaxNonceError error handling # Since nonce is increased after decryption as well, we need to generate a proper ciphertext in order to test MaxNonceError error handling
# We cannot call encryptWithAd to encrypt a plaintext using a nonce equal MaxNonce, since this will trigger a MaxNonceError. # We cannot call encryptWithAd to encrypt a plaintext using a nonce equal MaxNonce, since this will trigger a MaxNonceError.
@ -275,7 +275,7 @@ procSuite "Waku Noise":
cipherState = randomCipherState(rng[]) cipherState = randomCipherState(rng[])
setNonce(cipherState, NonceMax) setNonce(cipherState, NonceMax)
plaintext = randomSeqByte(rng[], rand(1..128)) plaintext = randomSeqByte(rng[], rand(1..128))
# We perform encryption using the Cipher State key, NonceMax and ad # We perform encryption using the Cipher State key, NonceMax and ad
# By Noise specification the nonce is 8 bytes long out of the 12 bytes supported by ChaChaPoly, thus we copy the Little endian conversion of the nonce to a ChaChaPolyNonce # By Noise specification the nonce is 8 bytes long out of the 12 bytes supported by ChaChaPoly, thus we copy the Little endian conversion of the nonce to a ChaChaPolyNonce
var var
@ -295,14 +295,14 @@ procSuite "Waku Noise":
for _ in [1..5]: for _ in [1..5]:
expect NoiseNonceMaxError: expect NoiseNonceMaxError:
plaintext = decryptWithAd(cipherState, ad, ciphertext) plaintext = decryptWithAd(cipherState, ad, ciphertext)
check: check:
getNonce(cipherState) == NonceMax + 1 getNonce(cipherState) == NonceMax + 1
test "Noise State Machine: Symmetric State primitives": test "Noise State Machine: Symmetric State primitives":
# We select one supported handshake pattern and we initialize a symmetric state # We select one supported handshake pattern and we initialize a symmetric state
var var
hsPattern = NoiseHandshakePatterns["XX"] hsPattern = NoiseHandshakePatterns["XX"]
symmetricState: SymmetricState = SymmetricState.init(hsPattern) symmetricState: SymmetricState = SymmetricState.init(hsPattern)
@ -343,7 +343,7 @@ procSuite "Waku Noise":
var inputKeyMaterial = randomSeqByte(rng[], rand(1..128)) var inputKeyMaterial = randomSeqByte(rng[], rand(1..128))
mixKey(symmetricState, inputKeyMaterial) mixKey(symmetricState, inputKeyMaterial)
# mixKey changes the Symmetric State's chaining key and encryption key of the embedded Cipher State # mixKey changes the Symmetric State's chaining key and encryption key of the embedded Cipher State
# It further sets to 0 the nonce of the embedded Cipher State # It further sets to 0 the nonce of the embedded Cipher State
check: check:
getKey(cs) != getKey(getCipherState(symmetricState)) getKey(cs) != getKey(getCipherState(symmetricState))
@ -399,7 +399,7 @@ procSuite "Waku Noise":
# We restore the symmetric State to its initial value to test decryption # We restore the symmetric State to its initial value to test decryption
symmetricState = initialSymmetricState symmetricState = initialSymmetricState
# We execute decryptAndHash over the ciphertext # We execute decryptAndHash over the ciphertext
var decrypted = decryptAndHash(symmetricState, ciphertext) var decrypted = decryptAndHash(symmetricState, ciphertext)
@ -422,7 +422,7 @@ procSuite "Waku Noise":
check: check:
getChainingKey(symmetricState) != EmptyKey getChainingKey(symmetricState) != EmptyKey
# When a Symmetric State's ck is non-empty, we can execute split, which creates two distinct Cipher States cs1 and cs2 # When a Symmetric State's ck is non-empty, we can execute split, which creates two distinct Cipher States cs1 and cs2
# with non-empty encryption keys and nonce set to 0 # with non-empty encryption keys and nonce set to 0
var (cs1, cs2) = split(symmetricState) var (cs1, cs2) = split(symmetricState)
@ -443,11 +443,11 @@ procSuite "Waku Noise":
let bobStaticKey = genKeyPair(rng[]) let bobStaticKey = genKeyPair(rng[])
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey) var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey)
var var
sentTransportMessage: seq[byte] sentTransportMessage: seq[byte]
aliceStep, bobStep: HandshakeStepResult aliceStep, bobStep: HandshakeStepResult
# Here the handshake starts # Here the handshake starts
# Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user # Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user
@ -458,20 +458,20 @@ procSuite "Waku Noise":
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message # By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message # and the (encrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
############### ###############
# 2nd step # 2nd step
############### ###############
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
@ -480,8 +480,8 @@ procSuite "Waku Noise":
# While Alice reads and returns the (decrypted) transport message # While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get() aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
check: check:
aliceStep.transportMessage == sentTransportMessage aliceStep.transportMessage == sentTransportMessage
############### ###############
@ -489,36 +489,36 @@ procSuite "Waku Noise":
############### ###############
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message # Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
# Note that for this handshake pattern, no more message patterns are left for processing # Note that for this handshake pattern, no more message patterns are left for processing
# Another call to stepHandshake would return an empty HandshakeStepResult # Another call to stepHandshake would return an empty HandshakeStepResult
# We test that extra calls to stepHandshake do not affect parties' handshake states # We test that extra calls to stepHandshake do not affect parties' handshake states
# and that the intermediate HandshakeStepResult are empty # and that the intermediate HandshakeStepResult are empty
let prevAliceHS = aliceHS let prevAliceHS = aliceHS
let prevBobHS = bobHS let prevBobHS = bobHS
let bobStep1 = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get() let bobStep1 = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
let aliceStep1 = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep1.payload2).get() let aliceStep1 = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep1.payload2).get()
let aliceStep2 = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() let aliceStep2 = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
let bobStep2 = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep2.payload2).get() let bobStep2 = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep2.payload2).get()
check: check:
aliceStep1 == default(HandshakeStepResult) aliceStep1 == default(HandshakeStepResult)
aliceStep2 == default(HandshakeStepResult) aliceStep2 == default(HandshakeStepResult)
bobStep1 == default(HandshakeStepResult) bobStep1 == default(HandshakeStepResult)
bobStep2 == default(HandshakeStepResult) bobStep2 == default(HandshakeStepResult)
aliceHS == prevAliceHS aliceHS == prevAliceHS
bobHS == prevBobHS bobHS == prevBobHS
######################### #########################
# After Handshake # After Handshake
@ -531,7 +531,7 @@ procSuite "Waku Noise":
bobHSResult = finalizeHandshake(bobHS) bobHSResult = finalizeHandshake(bobHS)
# We test read/write of random messages exchanged between Alice and Bob # We test read/write of random messages exchanged between Alice and Bob
var var
payload2: PayloadV2 payload2: PayloadV2
message: seq[byte] message: seq[byte]
readMessage: seq[byte] readMessage: seq[byte]
@ -543,15 +543,15 @@ procSuite "Waku Noise":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
# Bob writes to Alice # Bob writes to Alice
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
@ -561,18 +561,18 @@ procSuite "Waku Noise":
# We generate a random psk # We generate a random psk
let psk = randomSeqByte(rng[], 32) let psk = randomSeqByte(rng[], 32)
# We initialize Alice's and Bob's Handshake State # We initialize Alice's and Bob's Handshake State
let aliceStaticKey = genKeyPair(rng[]) let aliceStaticKey = genKeyPair(rng[])
var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, psk = psk, initiator = true) var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, psk = psk, initiator = true)
let bobStaticKey = genKeyPair(rng[]) let bobStaticKey = genKeyPair(rng[])
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, psk = psk) var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, psk = psk)
var var
sentTransportMessage: seq[byte] sentTransportMessage: seq[byte]
aliceStep, bobStep: HandshakeStepResult aliceStep, bobStep: HandshakeStepResult
# Here the handshake starts # Here the handshake starts
# Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user # Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user
@ -582,14 +582,14 @@ procSuite "Waku Noise":
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message # By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message # and the (encrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
@ -605,8 +605,8 @@ procSuite "Waku Noise":
# While Alice reads and returns the (decrypted) transport message # While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get() aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
check: check:
aliceStep.transportMessage == sentTransportMessage aliceStep.transportMessage == sentTransportMessage
############### ###############
@ -621,12 +621,12 @@ procSuite "Waku Noise":
# Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
# Note that for this handshake pattern, no more message patterns are left for processing # Note that for this handshake pattern, no more message patterns are left for processing
######################### #########################
# After Handshake # After Handshake
######################### #########################
@ -638,7 +638,7 @@ procSuite "Waku Noise":
bobHSResult = finalizeHandshake(bobHS) bobHSResult = finalizeHandshake(bobHS)
# We test read/write of random messages exchanged between Alice and Bob # We test read/write of random messages exchanged between Alice and Bob
var var
payload2: PayloadV2 payload2: PayloadV2
message: seq[byte] message: seq[byte]
readMessage: seq[byte] readMessage: seq[byte]
@ -650,15 +650,15 @@ procSuite "Waku Noise":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
# Bob writes to Alice # Bob writes to Alice
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
@ -679,11 +679,11 @@ procSuite "Waku Noise":
var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, preMessagePKs = preMessagePKs, initiator = true) var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, preMessagePKs = preMessagePKs, initiator = true)
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, preMessagePKs = preMessagePKs) var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, preMessagePKs = preMessagePKs)
var var
sentTransportMessage: seq[byte] sentTransportMessage: seq[byte]
aliceStep, bobStep: HandshakeStepResult aliceStep, bobStep: HandshakeStepResult
# Here the handshake starts # Here the handshake starts
# Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user # Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user
@ -691,16 +691,16 @@ procSuite "Waku Noise":
# 1st step # 1st step
############### ###############
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message # By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message # and the (encrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
@ -710,13 +710,13 @@ procSuite "Waku Noise":
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# At this step, Bob writes and returns a payload # At this step, Bob writes and returns a payload
bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get() bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
# While Alice reads and returns the (decrypted) transport message # While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get() aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
check: check:
aliceStep.transportMessage == sentTransportMessage aliceStep.transportMessage == sentTransportMessage
@ -732,12 +732,12 @@ procSuite "Waku Noise":
# Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
# Note that for this handshake pattern, no more message patterns are left for processing # Note that for this handshake pattern, no more message patterns are left for processing
######################### #########################
# After Handshake # After Handshake
######################### #########################
@ -749,7 +749,7 @@ procSuite "Waku Noise":
bobHSResult = finalizeHandshake(bobHS) bobHSResult = finalizeHandshake(bobHS)
# We test read/write of random messages between Alice and Bob # We test read/write of random messages between Alice and Bob
var var
payload2: PayloadV2 payload2: PayloadV2
message: seq[byte] message: seq[byte]
readMessage: seq[byte] readMessage: seq[byte]
@ -761,15 +761,15 @@ procSuite "Waku Noise":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
# Bob writes to Alice # Bob writes to Alice
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
@ -790,11 +790,11 @@ procSuite "Waku Noise":
var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, preMessagePKs = preMessagePKs, initiator = true) var aliceHS = initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, preMessagePKs = preMessagePKs, initiator = true)
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, preMessagePKs = preMessagePKs) var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, preMessagePKs = preMessagePKs)
var var
sentTransportMessage: seq[byte] sentTransportMessage: seq[byte]
aliceStep, bobStep: HandshakeStepResult aliceStep, bobStep: HandshakeStepResult
# Here the handshake starts # Here the handshake starts
# Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user # Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user
@ -805,13 +805,13 @@ procSuite "Waku Noise":
# We generate a random transport message # We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32) sentTransportMessage = randomSeqByte(rng[], 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message # By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message # and the (encrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
@ -827,7 +827,7 @@ procSuite "Waku Noise":
# While Alice reads and returns the (decrypted) transport message # While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get() aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
check: check:
aliceStep.transportMessage == sentTransportMessage aliceStep.transportMessage == sentTransportMessage
@ -843,12 +843,12 @@ procSuite "Waku Noise":
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
# Note that for this handshake pattern, no more message patterns are left for processing # Note that for this handshake pattern, no more message patterns are left for processing
######################### #########################
# After Handshake # After Handshake
######################### #########################
@ -860,7 +860,7 @@ procSuite "Waku Noise":
bobHSResult = finalizeHandshake(bobHS) bobHSResult = finalizeHandshake(bobHS)
# We test read/write of random messages exchanged between Alice and Bob # We test read/write of random messages exchanged between Alice and Bob
var var
payload2: PayloadV2 payload2: PayloadV2
message: seq[byte] message: seq[byte]
readMessage: seq[byte] readMessage: seq[byte]
@ -872,14 +872,14 @@ procSuite "Waku Noise":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage
# Bob writes to Alice # Bob writes to Alice
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer) payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get() readMessage = readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
check: check:
message == readMessage message == readMessage

View File

@ -1,12 +1,12 @@
{.used.} {.used.}
import import
std/[random,tables], std/[random, tables],
stew/byteutils, stew/[results, byteutils],
testutils/unittests, testutils/unittests,
libp2p/protobuf/minprotobuf libp2p/protobuf/minprotobuf
import import
../../waku/v2/node/waku_payload, ../../waku/v2/utils/noise as waku_message_utils,
../../waku/v2/protocol/waku_noise/noise_types, ../../waku/v2/protocol/waku_noise/noise_types,
../../waku/v2/protocol/waku_noise/noise_utils, ../../waku/v2/protocol/waku_noise/noise_utils,
../../waku/v2/protocol/waku_noise/noise_handshake_processing, ../../waku/v2/protocol/waku_noise/noise_handshake_processing,
@ -14,13 +14,13 @@ import
../test_helpers ../test_helpers
procSuite "Waku Noise Sessions": procSuite "Waku Noise Sessions":
# We initialize the RNG in test_helpers # We initialize the RNG in test_helpers
let rng = rng() let rng = rng()
# We initialize the RNG in std/random # We initialize the RNG in std/random
randomize() randomize()
# This test implements the Device pairing and Secure Transfers with Noise # This test implements the Device pairing and Secure Transfers with Noise
# detailed in the 43/WAKU2-DEVICE-PAIRING RFC https://rfc.vac.dev/spec/43/ # detailed in the 43/WAKU2-DEVICE-PAIRING RFC https://rfc.vac.dev/spec/43/
test "Noise Waku Pairing Handhshake and Secure transfer": test "Noise Waku Pairing Handhshake and Secure transfer":
@ -65,7 +65,7 @@ procSuite "Waku Noise Sessions":
bobCommittedStaticKey == readCommittedStaticKey bobCommittedStaticKey == readCommittedStaticKey
# We set the contentTopic from the content topic parameters exchanged in the QR # We set the contentTopic from the content topic parameters exchanged in the QR
let contentTopic: ContentTopic = "/" & applicationName & "/" & applicationVersion & "/wakunoise/1/sessions_shard-" & shardId & "/proto" let contentTopic: ContentTopic = "/" & applicationName & "/" & applicationVersion & "/wakunoise/1/sessions_shard-" & shardId & "/proto"
############### ###############
# Pre-handshake message # Pre-handshake message
@ -74,7 +74,7 @@ procSuite "Waku Noise Sessions":
############### ###############
let preMessagePKs: seq[NoisePublicKey] = @[toNoisePublicKey(getPublicKey(bobEphemeralKey))] let preMessagePKs: seq[NoisePublicKey] = @[toNoisePublicKey(getPublicKey(bobEphemeralKey))]
# We initialize the Handshake states. # We initialize the Handshake states.
# Note that we pass the whole qr serialization as prologue information # Note that we pass the whole qr serialization as prologue information
var aliceHS = initialize(hsPattern = hsPattern, ephemeralKey = aliceEphemeralKey, staticKey = aliceStaticKey, prologue = qr.toBytes, preMessagePKs = preMessagePKs, initiator = true) var aliceHS = initialize(hsPattern = hsPattern, ephemeralKey = aliceEphemeralKey, staticKey = aliceStaticKey, prologue = qr.toBytes, preMessagePKs = preMessagePKs, initiator = true)
var bobHS = initialize(hsPattern = hsPattern, ephemeralKey = bobEphemeralKey, staticKey = bobStaticKey, prologue = qr.toBytes, preMessagePKs = preMessagePKs) var bobHS = initialize(hsPattern = hsPattern, ephemeralKey = bobEphemeralKey, staticKey = bobStaticKey, prologue = qr.toBytes, preMessagePKs = preMessagePKs)
@ -82,25 +82,25 @@ procSuite "Waku Noise Sessions":
############### ###############
# Pairing Handshake # Pairing Handshake
############### ###############
var var
sentTransportMessage: seq[byte] sentTransportMessage: seq[byte]
aliceStep, bobStep: HandshakeStepResult aliceStep, bobStep: HandshakeStepResult
msgFromPb: ProtoResult[WakuMessage] msgFromPb: ProtoResult[WakuMessage]
wakuMsg: WakuResult[WakuMessage] wakuMsg: Result[WakuMessage, cstring]
pb: ProtoBuffer pb: ProtoBuffer
readPayloadV2: PayloadV2 readPayloadV2: PayloadV2
aliceMessageNametag, bobMessageNametag: MessageNametag aliceMessageNametag, bobMessageNametag: MessageNametag
# Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user # Write and read calls alternate between Alice and Bob: the handhshake progresses by alternatively calling stepHandshake for each user
############### ###############
# 1st step # 1st step
# #
# -> eA, eAeB {H(sA||s)} [authcode] # -> eA, eAeB {H(sA||s)} [authcode]
############### ###############
# The messageNametag for the first handshake message is randomly generated and exchanged out-of-band # The messageNametag for the first handshake message is randomly generated and exchanged out-of-band
# and corresponds to qrMessageNametag # and corresponds to qrMessageNametag
# We set the transport message to be H(sA||s) # We set the transport message to be H(sA||s)
@ -110,7 +110,7 @@ procSuite "Waku Noise Sessions":
check: check:
seqToDigest256(sentTransportMessage) == aliceCommittedStaticKey seqToDigest256(sentTransportMessage) == aliceCommittedStaticKey
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message # By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message # and the (encrypted) transport message
# The message is sent with a messageNametag equal to the one received through the QR code # The message is sent with a messageNametag equal to the one received through the QR code
aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage, messageNametag = qrMessageNametag).get() aliceStep = stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage, messageNametag = qrMessageNametag).get()
@ -129,7 +129,7 @@ procSuite "Waku Noise Sessions":
# We decode the WakuMessage from the ProtoBuffer # We decode the WakuMessage from the ProtoBuffer
msgFromPb = WakuMessage.decode(pb.buffer) msgFromPb = WakuMessage.decode(pb.buffer)
check: check:
msgFromPb.isOk() msgFromPb.isOk()
@ -143,18 +143,18 @@ procSuite "Waku Noise Sessions":
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
# Note that Bob verifies if the received payloadv2 has the expected messageNametag set # Note that Bob verifies if the received payloadv2 has the expected messageNametag set
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = qrMessageNametag).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = qrMessageNametag).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
# We generate an authorization code using the handshake state # We generate an authorization code using the handshake state
let aliceAuthcode = genAuthcode(aliceHS) let aliceAuthcode = genAuthcode(aliceHS)
let bobAuthcode = genAuthcode(bobHS) let bobAuthcode = genAuthcode(bobHS)
# We check that they are equal. Note that this check has to be confirmed with a user interaction. # We check that they are equal. Note that this check has to be confirmed with a user interaction.
check: check:
aliceAuthcode == bobAuthcode aliceAuthcode == bobAuthcode
############### ###############
# 2nd step # 2nd step
# #
@ -186,7 +186,7 @@ procSuite "Waku Noise Sessions":
# We decode the WakuMessage from the ProtoBuffer # We decode the WakuMessage from the ProtoBuffer
msgFromPb = WakuMessage.decode(pb.buffer) msgFromPb = WakuMessage.decode(pb.buffer)
check: check:
msgFromPb.isOk() msgFromPb.isOk()
@ -199,7 +199,7 @@ procSuite "Waku Noise Sessions":
# While Alice reads and returns the (decrypted) transport message # While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = readPayloadV2, messageNametag = aliceMessageNametag).get() aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = readPayloadV2, messageNametag = aliceMessageNametag).get()
check: check:
aliceStep.transportMessage == sentTransportMessage aliceStep.transportMessage == sentTransportMessage
@ -208,7 +208,7 @@ procSuite "Waku Noise Sessions":
check: check:
expectedBobCommittedStaticKey == bobCommittedStaticKey expectedBobCommittedStaticKey == bobCommittedStaticKey
############### ###############
# 3rd step # 3rd step
# #
@ -239,7 +239,7 @@ procSuite "Waku Noise Sessions":
# We decode the WakuMessage from the ProtoBuffer # We decode the WakuMessage from the ProtoBuffer
msgFromPb = WakuMessage.decode(pb.buffer) msgFromPb = WakuMessage.decode(pb.buffer)
check: check:
msgFromPb.isOk() msgFromPb.isOk()
@ -252,7 +252,7 @@ procSuite "Waku Noise Sessions":
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him # Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = bobMessageNametag).get() bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = bobMessageNametag).get()
check: check:
bobStep.transportMessage == sentTransportMessage bobStep.transportMessage == sentTransportMessage
@ -261,7 +261,7 @@ procSuite "Waku Noise Sessions":
check: check:
expectedAliceCommittedStaticKey == aliceCommittedStaticKey expectedAliceCommittedStaticKey == aliceCommittedStaticKey
######################### #########################
# Secure Transfer Phase # Secure Transfer Phase
######################### #########################
@ -273,7 +273,7 @@ procSuite "Waku Noise Sessions":
bobHSResult = finalizeHandshake(bobHS) bobHSResult = finalizeHandshake(bobHS)
# We test read/write of random messages exchanged between Alice and Bob # We test read/write of random messages exchanged between Alice and Bob
var var
payload2: PayloadV2 payload2: PayloadV2
message: seq[byte] message: seq[byte]
readMessage: seq[byte] readMessage: seq[byte]
@ -286,15 +286,15 @@ procSuite "Waku Noise Sessions":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(aliceHSResult, message, outboundMessageNametagBuffer = aliceHSResult.nametagsOutbound) payload2 = writeMessage(aliceHSResult, message, outboundMessageNametagBuffer = aliceHSResult.nametagsOutbound)
readMessage = readMessage(bobHSResult, payload2, inboundMessageNametagBuffer = bobHSResult.nametagsInbound).get() readMessage = readMessage(bobHSResult, payload2, inboundMessageNametagBuffer = bobHSResult.nametagsInbound).get()
check: check:
message == readMessage message == readMessage
# Bob writes to Alice # Bob writes to Alice
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, outboundMessageNametagBuffer = bobHSResult.nametagsOutbound) payload2 = writeMessage(bobHSResult, message, outboundMessageNametagBuffer = bobHSResult.nametagsOutbound)
readMessage = readMessage(aliceHSResult, payload2, inboundMessageNametagBuffer = aliceHSResult.nametagsInbound).get() readMessage = readMessage(aliceHSResult, payload2, inboundMessageNametagBuffer = aliceHSResult.nametagsInbound).get()
check: check:
message == readMessage message == readMessage
@ -312,7 +312,7 @@ procSuite "Waku Noise Sessions":
message = randomSeqByte(rng[], 32) message = randomSeqByte(rng[], 32)
payload2 = writeMessage(bobHSResult, message, outboundMessageNametagBuffer = bobHSResult.nametagsOutbound) payload2 = writeMessage(bobHSResult, message, outboundMessageNametagBuffer = bobHSResult.nametagsOutbound)
readMessage = readMessage(aliceHSResult, payload2, inboundMessageNametagBuffer = aliceHSResult.nametagsInbound).get() readMessage = readMessage(aliceHSResult, payload2, inboundMessageNametagBuffer = aliceHSResult.nametagsInbound).get()
check: check:
message == readMessage message == readMessage

View File

@ -7,13 +7,10 @@ import
import import
libp2p/protocols/ping, libp2p/protocols/ping,
libp2p/crypto/[crypto, secp], libp2p/crypto/[crypto, secp],
libp2p/nameresolving/nameresolver,
libp2p/nameresolving/dnsresolver libp2p/nameresolving/dnsresolver
import import
../../waku/v2/node/peer_manager, ../../waku/v2/node/peer_manager,
../../waku/v2/utils/peers,
../../waku/v2/node/waku_node, ../../waku/v2/node/waku_node,
../../waku/v2/node/waku_payload,
../../waku/v2/utils/peers ../../waku/v2/utils/peers
# protocols and their tag # protocols and their tag
@ -60,7 +57,7 @@ type
proc parseCmdArg*(T: type chronos.Duration, p: string): T = proc parseCmdArg*(T: type chronos.Duration, p: string): T =
try: try:
result = chronos.seconds(parseInt(p)) result = chronos.seconds(parseInt(p))
except CatchableError as e: except CatchableError:
raise newException(ConfigurationError, "Invalid timeout value") raise newException(ConfigurationError, "Invalid timeout value")
proc completeCmdArg*(T: type chronos.Duration, val: string): seq[string] = proc completeCmdArg*(T: type chronos.Duration, val: string): seq[string] =

View File

@ -9,8 +9,8 @@ import
../../protocol/waku_message, ../../protocol/waku_message,
../../protocol/waku_store, ../../protocol/waku_store,
../../protocol/waku_store/rpc, ../../protocol/waku_store/rpc,
../../utils/compat,
../../utils/time, ../../utils/time,
../waku_payload,
./hexstrings, ./hexstrings,
./jsonrpc_types ./jsonrpc_types

View File

@ -4,17 +4,18 @@ else:
{.push raises: [].} {.push raises: [].}
import import
std/[tables,sequtils], std/[tables, sequtils],
chronicles, chronicles,
eth/keys, eth/keys,
json_rpc/rpcserver, json_rpc/rpcserver,
nimcrypto/sysrand, nimcrypto/sysrand
import
../../utils/compat,
../waku_node, ../waku_node,
../waku_payload,
./jsonrpc_types, ./jsonrpc_types,
./jsonrpc_utils ./jsonrpc_utils
export waku_payload, jsonrpc_types export compat, jsonrpc_types
logScope: logScope:
topics = "waku node jsonrpc private_api" topics = "waku node jsonrpc private_api"
@ -25,7 +26,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: T
## Private API version 1 definitions ## Private API version 1 definitions
## Definitions for symmetric cryptography ## Definitions for symmetric cryptography
rpcsrv.rpc("get_waku_v2_private_v1_symmetric_key") do() -> SymKey: rpcsrv.rpc("get_waku_v2_private_v1_symmetric_key") do() -> SymKey:
## Generates and returns a symmetric key for message encryption and decryption ## Generates and returns a symmetric key for message encryption and decryption
debug "get_waku_v2_private_v1_symmetric_key" debug "get_waku_v2_private_v1_symmetric_key"
@ -42,7 +43,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: T
let msg = message.toWakuMessage(version = 1, let msg = message.toWakuMessage(version = 1,
rng = node.rng, rng = node.rng,
pubKey = none(waku_payload.PublicKey), pubKey = none(compat.PublicKey),
symkey = some(symkey.toSymKey())) symkey = some(symkey.toSymKey()))
if (await node.publish(topic, msg).withTimeout(futTimeout)): if (await node.publish(topic, msg).withTimeout(futTimeout)):
@ -56,7 +57,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: T
## Returns all WakuMessages received on a PubSub topic since the ## Returns all WakuMessages received on a PubSub topic since the
## last time this method was called. Decrypts the message payloads ## last time this method was called. Decrypts the message payloads
## before returning. ## before returning.
## ##
## @TODO ability to specify a return message limit ## @TODO ability to specify a return message limit
debug "get_waku_v2_private_v1_symmetric_messages", topic=topic debug "get_waku_v2_private_v1_symmetric_messages", topic=topic
@ -65,18 +66,18 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: T
# Clear cache before next call # Clear cache before next call
topicCache[topic] = @[] topicCache[topic] = @[]
return msgs.mapIt(it.toWakuRelayMessage(symkey = some(symkey.toSymKey()), return msgs.mapIt(it.toWakuRelayMessage(symkey = some(symkey.toSymKey()),
privateKey = none(waku_payload.PrivateKey))) privateKey = none(compat.PrivateKey)))
else: else:
# Not subscribed to this topic # Not subscribed to this topic
raise newException(ValueError, "Not subscribed to topic: " & topic) raise newException(ValueError, "Not subscribed to topic: " & topic)
## Definitions for asymmetric cryptography ## Definitions for asymmetric cryptography
rpcsrv.rpc("get_waku_v2_private_v1_asymmetric_keypair") do() -> WakuKeyPair: rpcsrv.rpc("get_waku_v2_private_v1_asymmetric_keypair") do() -> WakuKeyPair:
## Generates and returns a public/private key pair for asymmetric message encryption and decryption. ## Generates and returns a public/private key pair for asymmetric message encryption and decryption.
debug "get_waku_v2_private_v1_asymmetric_keypair" debug "get_waku_v2_private_v1_asymmetric_keypair"
let privKey = waku_payload.PrivateKey.random(node.rng[]) let privKey = compat.PrivateKey.random(node.rng[])
return WakuKeyPair(seckey: privKey, pubkey: privKey.toPublicKey()) return WakuKeyPair(seckey: privKey, pubkey: privKey.toPublicKey())
@ -100,7 +101,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: T
## Returns all WakuMessages received on a PubSub topic since the ## Returns all WakuMessages received on a PubSub topic since the
## last time this method was called. Decrypts the message payloads ## last time this method was called. Decrypts the message payloads
## before returning. ## before returning.
## ##
## @TODO ability to specify a return message limit ## @TODO ability to specify a return message limit
debug "get_waku_v2_private_v1_asymmetric_messages", topic=topic debug "get_waku_v2_private_v1_asymmetric_messages", topic=topic

View File

@ -2,8 +2,6 @@
## ##
## See https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-message.md ## See https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-message.md
## for spec. ## for spec.
##
## For payload content and encryption, see waku/v2/node/waku_payload.nim
when (NimMajor, NimMinor) < (1, 4): when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].} {.push raises: [Defect].}

View File

@ -3,13 +3,14 @@ when (NimMajor, NimMinor) < (1, 4):
else: else:
{.push raises: [].} {.push raises: [].}
import import
std/options, std/options,
eth/keys, stew/results,
eth/keys
import
../../whisper/whisper_types, ../../whisper/whisper_types,
../protocol/waku_message, ../protocol/waku_message
../protocol/waku_noise/noise_types,
../protocol/waku_noise/noise_utils
export whisper_types, keys, options export whisper_types, keys, options
@ -28,9 +29,6 @@ type
of None: of None:
discard discard
# NOTE: Currently only used here, if we start using it elsewhere pull it out.
WakuResult*[T] = Result[T, cstring]
# TODO: # TODO:
# - This is using `DecodedPayload` from Waku v1 / Whisper and could be altered # - This is using `DecodedPayload` from Waku v1 / Whisper and could be altered
@ -41,7 +39,7 @@ type
# - For now this `KeyInfo` is a bit silly also, but perhaps with v2 or # - For now this `KeyInfo` is a bit silly also, but perhaps with v2 or
# adjustments to Waku v1 encoding, it can be better. # adjustments to Waku v1 encoding, it can be better.
proc decodePayload*(message: WakuMessage, keyInfo: KeyInfo): proc decodePayload*(message: WakuMessage, keyInfo: KeyInfo):
WakuResult[DecodedPayload] = Result[DecodedPayload, cstring] =
case message.version case message.version
of 0: of 0:
return ok(DecodedPayload(payload:message.payload)) return ok(DecodedPayload(payload:message.payload))
@ -69,7 +67,7 @@ proc decodePayload*(message: WakuMessage, keyInfo: KeyInfo):
# TODO: same story as for `decodedPayload`, but then regarding the `Payload` # TODO: same story as for `decodedPayload`, but then regarding the `Payload`
# object. # object.
proc encode*(payload: Payload, version: uint32, rng: var HmacDrbgContext): proc encode*(payload: Payload, version: uint32, rng: var HmacDrbgContext):
WakuResult[seq[byte]] = Result[seq[byte], cstring] =
case version case version
of 0: of 0:
# This is rather silly # This is rather silly
@ -82,36 +80,3 @@ proc encode*(payload: Payload, version: uint32, rng: var HmacDrbgContext):
return err("Couldn't encode the payload") return err("Couldn't encode the payload")
else: else:
return err("Unsupported WakuMessage version") return err("Unsupported WakuMessage version")
# Decodes a WakuMessage to a PayloadV2
# Currently, this is just a wrapper over deserializePayloadV2 and encryption/decryption is done on top (no KeyInfo)
proc decodePayloadV2*(message: WakuMessage): WakuResult[PayloadV2]
{.raises: [Defect, NoiseMalformedHandshake, NoisePublicKeyError].} =
# We check message version (only 2 is supported in this proc)
case message.version
of 2:
# We attempt to decode the WakuMessage payload
let deserializedPayload2 = deserializePayloadV2(message.payload)
if deserializedPayload2.isOk():
return ok(deserializedPayload2.get())
else:
return err("Failed to decode WakuMessage")
else:
return err("Wrong message version while decoding payload")
# Encodes a PayloadV2 to a WakuMessage
# Currently, this is just a wrapper over serializePayloadV2 and encryption/decryption is done on top (no KeyInfo)
proc encodePayloadV2*(payload2: PayloadV2, contentTopic: ContentTopic = default(ContentTopic)): WakuResult[WakuMessage]
{.raises: [Defect, NoiseMalformedHandshake, NoisePublicKeyError].} =
# We attempt to encode the PayloadV2
let serializedPayload2 = serializePayloadV2(payload2)
if not serializedPayload2.isOk():
return err("Failed to encode PayloadV2")
# If successful, we create and return a WakuMessage
let msg = WakuMessage(payload: serializedPayload2.get(), version: 2, contentTopic: contentTopic)
return ok(msg)

44
waku/v2/utils/noise.nim Normal file
View File

@ -0,0 +1,44 @@
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}
import
stew/results
import
../protocol/waku_message,
../protocol/waku_noise/noise_types,
../protocol/waku_noise/noise_utils
# Decodes a WakuMessage to a PayloadV2
# Currently, this is just a wrapper over deserializePayloadV2 and encryption/decryption is done on top (no KeyInfo)
proc decodePayloadV2*(message: WakuMessage): Result[PayloadV2, cstring]
{.raises: [NoiseMalformedHandshake, NoisePublicKeyError].} =
# We check message version (only 2 is supported in this proc)
case message.version
of 2:
# We attempt to decode the WakuMessage payload
let deserializedPayload2 = deserializePayloadV2(message.payload)
if deserializedPayload2.isOk():
return ok(deserializedPayload2.get())
else:
return err("Failed to decode WakuMessage")
else:
return err("Wrong message version while decoding payload")
# Encodes a PayloadV2 to a WakuMessage
# Currently, this is just a wrapper over serializePayloadV2 and encryption/decryption is done on top (no KeyInfo)
proc encodePayloadV2*(payload2: PayloadV2, contentTopic: ContentTopic = default(ContentTopic)): Result[WakuMessage, cstring]
{.raises: [NoiseMalformedHandshake, NoisePublicKeyError].} =
# We attempt to encode the PayloadV2
let serializedPayload2 = serializePayloadV2(payload2)
if not serializedPayload2.isOk():
return err("Failed to encode PayloadV2")
# If successful, we create and return a WakuMessage
let msg = WakuMessage(payload: serializedPayload2.get(), version: 2, contentTopic: contentTopic)
return ok(msg)