github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/crypto/mac_test.go (about)

     1  package crypto
     2  
     3  import (
     4  	"math/rand"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  var testStrings = []string{"foo", "bar", "baz"}
    14  
    15  func TestMACMessageWithName(t *testing.T) {
    16  	value := []byte("myvalue")
    17  
    18  	k1 := []byte("0123456789012345")
    19  	k2 := []byte("0123456789012345")
    20  	k3 := []byte("9876543210987654")
    21  	o1 := MACConfig{Name: "message1"}
    22  	o2 := MACConfig{Name: ""}
    23  	o3 := MACConfig{Name: "message1"}
    24  
    25  	encoded, err1 := EncodeAuthMessage(o1, k1, value, nil)
    26  	require.NoError(t, err1)
    27  
    28  	v, err2 := DecodeAuthMessage(o1, k1, encoded, nil)
    29  	require.NoError(t, err2)
    30  
    31  	if !assert.EqualValues(t, v, value) {
    32  		t.Fatalf("Expected %v, got %v.", v, value)
    33  	}
    34  	_, err3 := DecodeAuthMessage(o2, k2, encoded, nil)
    35  	require.Error(t, err3)
    36  
    37  	_, err4 := DecodeAuthMessage(o3, k3, encoded, nil)
    38  	require.Error(t, err4)
    39  
    40  	_, err5 := DecodeAuthMessage(o1, k1, encoded, []byte("plop"))
    41  	require.Error(t, err5)
    42  
    43  	encoded2, err6 := EncodeAuthMessage(o1, k1, value, []byte("foo"))
    44  	require.NoError(t, err6)
    45  
    46  	_, err7 := DecodeAuthMessage(o1, k1, encoded2, []byte("foo"))
    47  	require.NoError(t, err7)
    48  
    49  	_, err8 := DecodeAuthMessage(o1, k1, encoded2, []byte("plop"))
    50  	require.Error(t, err8)
    51  }
    52  
    53  func TestMACMessageWithoutName(t *testing.T) {
    54  	value := []byte("myvalue")
    55  
    56  	k1 := []byte("0123456789012345")
    57  	k2 := []byte("0123456789012345")
    58  	k3 := []byte("9876543210987654")
    59  	o1 := MACConfig{Name: ""}
    60  	o2 := MACConfig{Name: "message1"}
    61  	o3 := MACConfig{Name: ""}
    62  
    63  	encoded, err1 := EncodeAuthMessage(o1, k1, value, nil)
    64  	require.NoError(t, err1)
    65  
    66  	v, err2 := DecodeAuthMessage(o1, k1, encoded, nil)
    67  	require.NoError(t, err2)
    68  
    69  	if !reflect.DeepEqual(v, value) {
    70  		t.Fatalf("Expected %v, got %v.", value, v)
    71  	}
    72  	_, err3 := DecodeAuthMessage(o2, k2, encoded, nil)
    73  	require.Error(t, err3)
    74  
    75  	_, err4 := DecodeAuthMessage(o3, k3, encoded, nil)
    76  	require.Error(t, err4)
    77  }
    78  
    79  func TestMACWrongMessage(t *testing.T) {
    80  	k := []byte("0123456789012345")
    81  	o := MACConfig{
    82  		Name:   "name",
    83  		MaxLen: 256,
    84  	}
    85  
    86  	{
    87  		_, err := DecodeAuthMessage(o, k, []byte(""), nil)
    88  		require.Equal(t, errMACInvalid, err)
    89  	}
    90  
    91  	{
    92  		_, err := DecodeAuthMessage(o, k, []byte("ccc"), nil)
    93  		require.Equal(t, errMACInvalid, err)
    94  	}
    95  
    96  	{
    97  		buf := Base64Encode(GenerateRandomBytes(32))
    98  		_, err := DecodeAuthMessage(o, k, buf, nil)
    99  		require.Equal(t, errMACInvalid, err)
   100  	}
   101  
   102  	{
   103  		buf := Base64Encode(createMAC(k, []byte("")))
   104  		_, err := DecodeAuthMessage(o, k, buf, nil)
   105  		require.Equal(t, errMACInvalid, err)
   106  	}
   107  
   108  	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
   109  	for i := 0; i < 10000; i++ {
   110  		buf := Base64Encode(GenerateRandomBytes(rng.Intn(1000)))
   111  		_, err := DecodeAuthMessage(o, k, buf, nil)
   112  		require.Equal(t, errMACInvalid, err)
   113  	}
   114  }
   115  
   116  func TestMACMaxAge(t *testing.T) {
   117  	key := GenerateRandomBytes(16)
   118  	val := []byte("coucou")
   119  	add := []byte("additional")
   120  	c1 := MACConfig{
   121  		Name:   "max",
   122  		MaxAge: 1 * time.Second,
   123  	}
   124  	c2 := MACConfig{
   125  		Name:   "max",
   126  		MaxAge: 10 * time.Second,
   127  	}
   128  
   129  	var msg1, msg2 []byte
   130  
   131  	{
   132  		var err error
   133  		msg1, err = EncodeAuthMessage(c1, key, val, add)
   134  		require.NoError(t, err)
   135  
   136  		msg2, err = EncodeAuthMessage(c2, key, val, add)
   137  		require.NoError(t, err)
   138  	}
   139  
   140  	{
   141  		ret1, err := DecodeAuthMessage(c1, key, msg1, add)
   142  		require.NoError(t, err)
   143  
   144  		assert.Equal(t, val, ret1)
   145  
   146  		ret2, err := DecodeAuthMessage(c2, key, msg2, add)
   147  		require.NoError(t, err)
   148  
   149  		assert.Equal(t, val, ret2)
   150  	}
   151  
   152  	time.Sleep(1500 * time.Millisecond)
   153  
   154  	{
   155  		ret1, err := DecodeAuthMessage(c1, key, msg1, add)
   156  		assert.Error(t, err)
   157  		assert.Nil(t, ret1)
   158  		assert.Equal(t, errMACExpired, err)
   159  
   160  		ret2, err := DecodeAuthMessage(c2, key, msg2, add)
   161  		assert.NoError(t, err)
   162  		assert.Equal(t, val, ret2)
   163  	}
   164  }
   165  
   166  func TestAuthentication(t *testing.T) {
   167  	hashKey := []byte("secret-key")
   168  	for _, value := range testStrings {
   169  		mac := createMAC(hashKey, []byte(value))
   170  		require.Len(t, mac, macLen)
   171  
   172  		ok1 := verifyMAC(hashKey, []byte(value), mac)
   173  		require.True(t, ok1)
   174  
   175  		ok2 := verifyMAC(hashKey, GenerateRandomBytes(32), mac)
   176  		require.False(t, ok2)
   177  	}
   178  }