test: payload encoding / decoding (#96)

This commit is contained in:
Richard Ramos 2021-10-21 08:18:14 -04:00 committed by GitHub
parent 9ad06b6eb8
commit 59e4a11b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 200 additions and 10 deletions

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
crand "crypto/rand" crand "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt"
mrand "math/rand" mrand "math/rand"
"errors" "errors"
@ -70,22 +71,38 @@ func (payload Payload) Encode(version uint32) ([]byte, error) {
case Symmetric: case Symmetric:
encoded, err := encryptSymmetric(data, payload.Key.SymKey) encoded, err := encryptSymmetric(data, payload.Key.SymKey)
if err != nil { if err != nil {
return nil, errors.New("Couldn't encrypt using symmetric key") return nil, fmt.Errorf("couldn't encrypt using symmetric key: %w", err)
} else { } else {
return encoded, nil return encoded, nil
} }
case Asymmetric: case Asymmetric:
encoded, err := encryptAsymmetric(data, &payload.Key.PubKey) encoded, err := encryptAsymmetric(data, &payload.Key.PubKey)
if err != nil { if err != nil {
return nil, errors.New("Couldn't encrypt using asymmetric key") return nil, fmt.Errorf("couldn't encrypt using asymmetric key: %w", err)
} else { } else {
return encoded, nil return encoded, nil
} }
case None: case None:
return nil, errors.New("Non supported KeyKind") return nil, errors.New("non supported KeyKind")
} }
} }
return nil, errors.New("Unsupported WakuMessage version") return nil, errors.New("unsupported wakumessage version")
}
func EncodeWakuMessage(message *pb.WakuMessage, keyInfo *KeyInfo) error {
msgPayload := message.Payload
payload := Payload{
Data: msgPayload,
Key: keyInfo,
}
encodedBytes, err := payload.Encode(message.Version)
if err != nil {
return err
}
message.Payload = encodedBytes
return nil
} }
// Decodes a WakuMessage depending on the version parameter. // Decodes a WakuMessage depending on the version parameter.
@ -98,12 +115,12 @@ func DecodePayload(message *pb.WakuMessage, keyInfo *KeyInfo) (*DecodedPayload,
switch keyInfo.Kind { switch keyInfo.Kind {
case Symmetric: case Symmetric:
if keyInfo.SymKey == nil { if keyInfo.SymKey == nil {
return nil, errors.New("Symmetric key is required") return nil, errors.New("symmetric key is required")
} }
decodedData, err := decryptSymmetric(message.Payload, keyInfo.SymKey) decodedData, err := decryptSymmetric(message.Payload, keyInfo.SymKey)
if err != nil { if err != nil {
return nil, errors.New("Couldn't decrypt using symmetric key") return nil, fmt.Errorf("couldn't decrypt using symmetric key: %w", err)
} }
decodedPayload, err := validateAndParse(decodedData) decodedPayload, err := validateAndParse(decodedData)
@ -114,12 +131,12 @@ func DecodePayload(message *pb.WakuMessage, keyInfo *KeyInfo) (*DecodedPayload,
return decodedPayload, nil return decodedPayload, nil
case Asymmetric: case Asymmetric:
if keyInfo.PrivKey == nil { if keyInfo.PrivKey == nil {
return nil, errors.New("Private key is required") return nil, errors.New("private key is required")
} }
decodedData, err := decryptAsymmetric(message.Payload, keyInfo.PrivKey) decodedData, err := decryptAsymmetric(message.Payload, keyInfo.PrivKey)
if err != nil { if err != nil {
return nil, errors.New("Couldn't decrypt using asymmetric key") return nil, fmt.Errorf("couldn't decrypt using asymmetric key: %w", err)
} }
decodedPayload, err := validateAndParse(decodedData) decodedPayload, err := validateAndParse(decodedData)
@ -129,10 +146,20 @@ func DecodePayload(message *pb.WakuMessage, keyInfo *KeyInfo) (*DecodedPayload,
return decodedPayload, nil return decodedPayload, nil
case None: case None:
return nil, errors.New("Non supported KeyKind") return nil, errors.New("non supported KeyKind")
} }
} }
return nil, errors.New("Unsupported WakuMessage version") return nil, errors.New("unsupported wakumessage version")
}
func DecodeWakuMessage(message *pb.WakuMessage, keyInfo *KeyInfo) error {
decodedPayload, err := DecodePayload(message, keyInfo)
if err != nil {
return err
}
message.Payload = decodedPayload.Data
return nil
} }
const aesNonceLength = 12 const aesNonceLength = 12

View File

@ -0,0 +1,163 @@
package node
import (
"fmt"
"testing"
"github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/stretchr/testify/require"
)
func createTestMsg() *pb.WakuMessage {
message := new(pb.WakuMessage)
message.Payload = []byte{0, 1, 2}
message.Version = 0
message.Timestamp = float64(123456)
return message
}
func TestEncodeDecodePayload(t *testing.T) {
data := []byte{0, 1, 2}
version := uint32(0)
keyInfo := new(KeyInfo)
keyInfo.Kind = None
p := Payload{
Data: data,
Key: keyInfo,
}
encodedPayload, err := p.Encode(version)
require.NoError(t, err)
require.Equal(t, data, encodedPayload)
message := new(pb.WakuMessage)
message.Payload = encodedPayload
message.Version = version
message.Timestamp = float64(123456)
decodedPayload, err := DecodePayload(message, keyInfo)
require.NoError(t, err)
require.Equal(t, data, decodedPayload.Data)
}
func TestEncodeDecodeVersion0(t *testing.T) {
message := createTestMsg()
keyInfo := new(KeyInfo)
keyInfo.Kind = None
err := EncodeWakuMessage(message, keyInfo)
require.NoError(t, err)
err = DecodeWakuMessage(message, keyInfo)
require.NoError(t, err)
}
func generateSymKey() ([]byte, error) {
key, err := generateSecureRandomData(aesKeyLength)
if err != nil {
return nil, err
} else if !validateDataIntegrity(key, aesKeyLength) {
return nil, fmt.Errorf("error in generating symkey: crypto/rand failed to generate random data")
}
return key, nil
}
func TestEncodeDecodeVersion1Symmetric(t *testing.T) {
message := createTestMsg()
message.Version = 1
data := message.Payload
keyInfo := new(KeyInfo)
keyInfo.Kind = Symmetric
var err error
keyInfo.SymKey, err = generateSymKey()
require.NoError(t, err)
err = EncodeWakuMessage(message, keyInfo)
require.NoError(t, err)
require.NotEqual(t, data, message.Payload)
require.NotNil(t, message.Payload)
err = DecodeWakuMessage(message, keyInfo)
require.NoError(t, err)
require.Equal(t, data, message.Payload)
}
func TestEncodeDecodeVersion1Asymmetric(t *testing.T) {
message := createTestMsg()
message.Version = 1
data := message.Payload
privKey, err := crypto.GenerateKey()
require.NoError(t, err)
keyInfo := new(KeyInfo)
keyInfo.Kind = Asymmetric
keyInfo.PubKey = privKey.PublicKey
err = EncodeWakuMessage(message, keyInfo)
require.NoError(t, err)
require.NotEqual(t, data, message.Payload)
require.NotNil(t, message.Payload)
keyInfo.PrivKey = privKey
err = DecodeWakuMessage(message, keyInfo)
require.NoError(t, err)
require.Equal(t, data, message.Payload)
}
func TestEncodeDecodeIncorrectKey(t *testing.T) {
message := createTestMsg()
message.Version = 1
privKey, err := crypto.GenerateKey()
require.NoError(t, err)
symKey, err := generateSymKey()
require.NoError(t, err)
keyInfo := new(KeyInfo)
keyInfo.Kind = Asymmetric
keyInfo.SymKey = symKey
err = EncodeWakuMessage(message, keyInfo)
require.Error(t, err)
keyInfo.SymKey = nil
keyInfo.PrivKey = privKey
err = EncodeWakuMessage(message, keyInfo)
require.Error(t, err)
}
func TestEncodeUnsupportedVersion(t *testing.T) {
message := createTestMsg()
message.Version = 99
keyInfo := new(KeyInfo)
keyInfo.Kind = None
err := EncodeWakuMessage(message, keyInfo)
require.Error(t, err)
require.Equal(t, "unsupported wakumessage version", err.Error())
}
func TestDecodeUnsupportedVersion(t *testing.T) {
message := createTestMsg()
message.Version = 99
keyInfo := new(KeyInfo)
keyInfo.Kind = None
decodedPayload, err := DecodePayload(message, keyInfo)
require.Nil(t, decodedPayload)
require.Error(t, err)
require.Equal(t, "unsupported wakumessage version", err.Error())
}