Compare commits

...

3 Commits

Author SHA1 Message Date
Igor Sirotin
a3d8b94a14
chore: update license files to comply with Logos licensing requirements 2026-02-05 15:09:25 +00:00
Richard Ramos
d654270130
fix: endianness of nonce function 2022-12-21 12:46:15 -04:00
Richard Ramos
962299d8b4
fix: payload serialization 2022-12-21 11:56:30 -04:00
6 changed files with 46 additions and 29 deletions

View File

@ -1,6 +1,3 @@
nim-waku is licensed under the Apache License version 2
Copyright (c) 2018 Status Research & Development GmbH
-----------------------------------------------------
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
@ -190,7 +187,7 @@ Copyright (c) 2018 Status Research & Development GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2018 Status Research & Development GmbH Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,25 +1,21 @@
nim-waku is licensed under the MIT License
Copyright (c) 2018 Status Research & Development GmbH
-----------------------------------------------------
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2018 Status Research & Development GmbH Copyright © 2025-2026 Logos
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in
copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
SOFTWARE. THE SOFTWARE.

View File

@ -67,8 +67,10 @@ func (c *CipherState) hasKey() bool {
} }
func (cs *CipherState) nonce() []byte { func (cs *CipherState) nonce() []byte {
var nonceBytes [12]byte // RFC7539 specifies 12 bytes for nonce. // RFC7539 specifies 12 bytes for nonce.
binary.BigEndian.PutUint64(nonceBytes[4:], cs.n) // TODO: extract this to function setup when creating handshake pattern
var nonceBytes [12]byte
binary.LittleEndian.PutUint64(nonceBytes[4:], cs.n)
return nonceBytes[:] return nonceBytes[:]
} }

View File

@ -126,7 +126,13 @@ func handshakeTest(t *testing.T, hsAlice *Handshake, hsBob *Handshake) {
encryptedPayload, err := aliceHSResult.WriteMessage(message, defaultMessageNametagBuffer) encryptedPayload, err := aliceHSResult.WriteMessage(message, defaultMessageNametagBuffer)
require.NoError(t, err) require.NoError(t, err)
plaintext, err := bobHSResult.ReadMessage(encryptedPayload, defaultMessageNametagBuffer) serializedPayload, err := encryptedPayload.Serialize()
require.NoError(t, err)
deserializedPayload, err := DeserializePayloadV2(serializedPayload)
require.NoError(t, err)
plaintext, err := bobHSResult.ReadMessage(deserializedPayload, defaultMessageNametagBuffer)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, message, plaintext) require.Equal(t, message, plaintext)
@ -137,7 +143,13 @@ func handshakeTest(t *testing.T, hsAlice *Handshake, hsBob *Handshake) {
encryptedPayload, err = bobHSResult.WriteMessage(message, defaultMessageNametagBuffer) encryptedPayload, err = bobHSResult.WriteMessage(message, defaultMessageNametagBuffer)
require.NoError(t, err) require.NoError(t, err)
plaintext, err = aliceHSResult.ReadMessage(encryptedPayload, defaultMessageNametagBuffer) serializedPayload, err = encryptedPayload.Serialize()
require.NoError(t, err)
deserializedPayload, err = DeserializePayloadV2(serializedPayload)
require.NoError(t, err)
plaintext, err = aliceHSResult.ReadMessage(deserializedPayload, defaultMessageNametagBuffer)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, message, plaintext) require.Equal(t, message, plaintext)

View File

@ -104,15 +104,17 @@ type HandshakePattern struct {
messagePatterns []MessagePattern messagePatterns []MessagePattern
hashFn func() hash.Hash hashFn func() hash.Hash
cipherFn func([]byte) (cipher.AEAD, error) cipherFn func([]byte) (cipher.AEAD, error)
tagSize int
dhKey DHKey dhKey DHKey
} }
func NewHandshakePattern(protocolID byte, name string, hashFn func() hash.Hash, cipherFn func([]byte) (cipher.AEAD, error), dhKey DHKey, preMessagePatterns []PreMessagePattern, messagePatterns []MessagePattern) HandshakePattern { func NewHandshakePattern(protocolID byte, name string, hashFn func() hash.Hash, cipherFn func([]byte) (cipher.AEAD, error), tagSize int, dhKey DHKey, preMessagePatterns []PreMessagePattern, messagePatterns []MessagePattern) HandshakePattern {
return HandshakePattern{ return HandshakePattern{
protocolID: protocolID, protocolID: protocolID,
name: name, name: name,
hashFn: hashFn, hashFn: hashFn,
cipherFn: cipherFn, cipherFn: cipherFn,
tagSize: tagSize,
dhKey: dhKey, dhKey: dhKey,
premessagePatterns: preMessagePatterns, premessagePatterns: preMessagePatterns,
messagePatterns: messagePatterns, messagePatterns: messagePatterns,
@ -153,6 +155,7 @@ var K1K1 = NewHandshakePattern(
"Noise_K1K1_25519_ChaChaPoly_SHA256", "Noise_K1K1_25519_ChaChaPoly_SHA256",
sha256.New, sha256.New,
chacha20poly1305.New, chacha20poly1305.New,
16,
DH25519, DH25519,
[]PreMessagePattern{ []PreMessagePattern{
NewPreMessagePattern(Right, []NoiseTokens{S}), NewPreMessagePattern(Right, []NoiseTokens{S}),
@ -170,6 +173,7 @@ var XK1 = NewHandshakePattern(
"Noise_XK1_25519_ChaChaPoly_SHA256", "Noise_XK1_25519_ChaChaPoly_SHA256",
sha256.New, sha256.New,
chacha20poly1305.New, chacha20poly1305.New,
16,
DH25519, DH25519,
[]PreMessagePattern{ []PreMessagePattern{
NewPreMessagePattern(Left, []NoiseTokens{S}), NewPreMessagePattern(Left, []NoiseTokens{S}),
@ -186,6 +190,7 @@ var XX = NewHandshakePattern(
"Noise_XX_25519_ChaChaPoly_SHA256", "Noise_XX_25519_ChaChaPoly_SHA256",
sha256.New, sha256.New,
chacha20poly1305.New, chacha20poly1305.New,
16,
DH25519, DH25519,
EmptyPreMessage, EmptyPreMessage,
[]MessagePattern{ []MessagePattern{
@ -200,6 +205,7 @@ var XXpsk0 = NewHandshakePattern(
"Noise_XXpsk0_25519_ChaChaPoly_SHA256", "Noise_XXpsk0_25519_ChaChaPoly_SHA256",
sha256.New, sha256.New,
chacha20poly1305.New, chacha20poly1305.New,
16,
DH25519, DH25519,
EmptyPreMessage, EmptyPreMessage,
[]MessagePattern{ []MessagePattern{
@ -214,6 +220,7 @@ var WakuPairing = NewHandshakePattern(
"Noise_WakuPairing_25519_ChaChaPoly_SHA256", "Noise_WakuPairing_25519_ChaChaPoly_SHA256",
sha256.New, sha256.New,
chacha20poly1305.New, chacha20poly1305.New,
16,
DH25519, DH25519,
[]PreMessagePattern{ []PreMessagePattern{
NewPreMessagePattern(Left, []NoiseTokens{E}), NewPreMessagePattern(Left, []NoiseTokens{E}),

View File

@ -2,7 +2,6 @@ package noise
import ( import (
"bytes" "bytes"
"crypto/ed25519"
"encoding/binary" "encoding/binary"
"errors" "errors"
) )
@ -106,8 +105,6 @@ func (p *PayloadV2) Serialize() ([]byte, error) {
return payloadBuf.Bytes(), nil return payloadBuf.Bytes(), nil
} }
const ChaChaPolyTagSize = byte(16)
// Deserializes a byte sequence to a PayloadV2 object according to https://rfc.vac.dev/spec/35/. // Deserializes a byte sequence to a PayloadV2 object according to https://rfc.vac.dev/spec/35/.
// The input serialized payload concatenates the output PayloadV2 object fields as // The input serialized payload concatenates the output PayloadV2 object fields as
// payload = ( protocolId || serializedHandshakeMessageLen || serializedHandshakeMessage || transportMessageLen || transportMessage) // payload = ( protocolId || serializedHandshakeMessageLen || serializedHandshakeMessage || transportMessageLen || transportMessage)
@ -126,8 +123,14 @@ func DeserializePayloadV2(payload []byte) (*PayloadV2, error) {
return nil, err return nil, err
} }
if !IsProtocolIDSupported(result.ProtocolId) { var pattern HandshakePattern
return nil, errors.New("unsupported protocol") var err error
if result.ProtocolId != None {
pattern, err = GetHandshakePattern(result.ProtocolId)
if err != nil {
return nil, err
}
} }
// We read the Handshake Message length (1 byte) // We read the Handshake Message length (1 byte)
@ -150,13 +153,13 @@ func DeserializePayloadV2(payload []byte) (*PayloadV2, error) {
if flag == 0 { if flag == 0 {
// If the key is unencrypted, we only read the X coordinate of the EC public key and we deserialize into a Noise Public Key // If the key is unencrypted, we only read the X coordinate of the EC public key and we deserialize into a Noise Public Key
pkLen := ed25519.PublicKeySize pkLen := pattern.dhKey.DHLen()
var pkBytes SerializedNoisePublicKey = make([]byte, pkLen) var pkBytes SerializedNoisePublicKey = make([]byte, pkLen)
if err := binary.Read(payloadBuf, binary.BigEndian, &pkBytes); err != nil { if err := binary.Read(payloadBuf, binary.BigEndian, &pkBytes); err != nil {
return nil, err return nil, err
} }
serializedPK := SerializedNoisePublicKey(make([]byte, ed25519.PublicKeySize+1)) serializedPK := SerializedNoisePublicKey(make([]byte, pkLen+1))
serializedPK[0] = flag serializedPK[0] = flag
copy(serializedPK[1:], pkBytes) copy(serializedPK[1:], pkBytes)
@ -169,7 +172,7 @@ func DeserializePayloadV2(payload []byte) (*PayloadV2, error) {
written += uint8(1 + pkLen) written += uint8(1 + pkLen)
} else if flag == 1 { } else if flag == 1 {
// If the key is encrypted, we only read the encrypted X coordinate and the authorization tag, and we deserialize into a Noise Public Key // If the key is encrypted, we only read the encrypted X coordinate and the authorization tag, and we deserialize into a Noise Public Key
pkLen := ed25519.PublicKeySize + ChaChaPolyTagSize pkLen := pattern.dhKey.DHLen() + pattern.tagSize
// TODO: duplicated code: ============== // TODO: duplicated code: ==============
var pkBytes SerializedNoisePublicKey = make([]byte, pkLen) var pkBytes SerializedNoisePublicKey = make([]byte, pkLen)
@ -177,7 +180,7 @@ func DeserializePayloadV2(payload []byte) (*PayloadV2, error) {
return nil, err return nil, err
} }
serializedPK := SerializedNoisePublicKey(make([]byte, ed25519.PublicKeySize+1)) serializedPK := SerializedNoisePublicKey(make([]byte, pkLen+1))
serializedPK[0] = flag serializedPK[0] = flag
copy(serializedPK[1:], pkBytes) copy(serializedPK[1:], pkBytes)