waku-org/go-waku

View on GitHub
waku/v2/payload/waku_payload_crypto_test.go

Summary

Maintainability
A
0 mins
Test Coverage
package payload

import (
    "crypto/aes"
    "crypto/cipher"
    crand "crypto/rand"
    mrand "math/rand"
    "testing"

    "github.com/ethereum/go-ethereum/common/hexutil"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/stretchr/testify/require"
)

func singleMessageTest(t *testing.T, symmetric bool) {
    message := createTestMsg(1)
    data := message.Payload

    var err error

    keyInfo := new(KeyInfo)
    keyInfo.PrivKey, err = crypto.GenerateKey()
    require.NoError(t, err)
    if symmetric {
        keyInfo.Kind = Symmetric
        keyInfo.SymKey, err = generateSymKey()
        require.NoError(t, err)
    } else {
        keyInfo.Kind = Asymmetric
        keyInfo.PubKey = keyInfo.PrivKey.PublicKey // We'll simulate 'sending' a message to ourselves
    }

    err = EncodeWakuMessage(message, keyInfo)
    require.NoError(t, err)

    var decryptedPayload []byte
    if symmetric {
        decryptedPayload, err = decryptSymmetric(message.Payload, keyInfo.SymKey)
        require.NoError(t, err)
    } else {
        decryptedPayload, err = decryptAsymmetric(message.Payload, keyInfo.PrivKey)
        require.NoError(t, err)
    }

    decodedPayload, err := validateAndParse(decryptedPayload)
    require.NoError(t, err)
    require.Equal(t, data, decodedPayload.Data)

    require.True(t, isMessageSigned(decryptedPayload[0]))
    require.Len(t, decodedPayload.Signature, signatureLength)
    require.Equal(t, keyInfo.PrivKey.PublicKey, *decodedPayload.PubKey)
}

func TestMessageEncryption(t *testing.T) {
    var symmetric bool
    for i := 0; i < 256; i++ {
        singleMessageTest(t, symmetric)
        symmetric = !symmetric
    }
}

func TestEncryptWithZeroKey(t *testing.T) {
    message := createTestMsg(1)

    keyInfo := new(KeyInfo)
    keyInfo.Kind = Symmetric
    keyInfo.SymKey = make([]byte, aesKeyLength)

    err := EncodeWakuMessage(message, keyInfo)
    require.Error(t, err)
    require.EqualError(t, err, "couldn't encrypt using symmetric key: invalid key provided for symmetric encryption, size: 32")
}

func singlePaddingTest(t *testing.T, padSize int) {
    var err error

    keyInfo := new(KeyInfo)
    keyInfo.Kind = Symmetric
    keyInfo.SymKey, err = generateSymKey()
    require.NoError(t, err)

    p := Payload{
        Data:    []byte{0, 1, 2},
        Padding: make([]byte, padSize),
        Key:     keyInfo,
    }

    _, err = crand.Read(p.Padding) // nolint: gosec
    require.NoError(t, err)

    encodedPayload, err := p.Encode(1)
    require.NoError(t, err)

    decodedData, err := decryptSymmetric(encodedPayload, keyInfo.SymKey)
    require.NoError(t, err)

    decodedPayload, err := validateAndParse(decodedData)
    require.NoError(t, err)

    require.Equal(t, p.Padding, decodedPayload.Padding)
}

func TestPadding(t *testing.T) {
    for i := 1; i < 260; i++ {
        singlePaddingTest(t, i)
    }

    lim := 256 * 256
    for i := lim - 5; i < lim+2; i++ {
        singlePaddingTest(t, i)
    }

    for i := 0; i < 256; i++ {
        n := mrand.Intn(256*254) + 256 // nolint: gosec
        singlePaddingTest(t, n)
    }

    for i := 0; i < 256; i++ {
        n := mrand.Intn(256*1024) + 256*256 // nolint: gosec
        singlePaddingTest(t, n)
    }
}

func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
    pSrc, err := crypto.GenerateKey()
    require.NoError(t, err)

    p := Payload{
        Data: make([]byte, 246),
        Key: &KeyInfo{
            Kind:    Symmetric,
            SymKey:  make([]byte, aesKeyLength),
            PrivKey: pSrc,
        },
    }

    // Simulate a message with a payload just under 256 so that
    // payload + flag + signature > 256. Check that the result
    // is padded on the next 256 boundary.
    const payloadSizeFieldMinSize = 1
    rawMessage := make([]byte, flagsLength+payloadSizeFieldMinSize+len(p.Data))
    rawMessage, err = p.appendPadding(rawMessage)

    require.NoError(t, err)
    require.Equal(t, 512-signatureLength, len(rawMessage))
}

func TestAesNonce(t *testing.T) {
    key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31")
    block, err := aes.NewCipher(key)
    require.NoError(t, err)

    aesgcm, err := cipher.NewGCM(block)
    require.NoError(t, err)
    require.Equal(t, aesgcm.NonceSize(), aesNonceLength)
}