github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfshash/hash_test.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package kbfshash 6 7 import ( 8 "testing" 9 10 "github.com/keybase/client/go/kbfs/kbfscodec" 11 "github.com/pkg/errors" 12 "github.com/stretchr/testify/require" 13 ) 14 15 // Make sure Hash encodes and decodes properly with minimal overhead. 16 func TestHashEncodeDecode(t *testing.T) { 17 codec := kbfscodec.NewMsgpack() 18 h, err := DefaultHash([]byte{1}) 19 require.NoError(t, err) 20 21 encodedH, err := codec.Encode(h) 22 require.NoError(t, err) 23 24 // See 25 // https://github.com/msgpack/msgpack/blob/master/spec.md#formats-bin 26 // for why there are two bytes of overhead. 27 const overhead = 2 28 require.Equal(t, DefaultHashByteLength+overhead, len(encodedH)) 29 30 var h2 Hash 31 err = codec.Decode(encodedH, &h2) 32 require.NoError(t, err) 33 34 require.Equal(t, h, h2) 35 } 36 37 // Make sure the zero Hash value encodes and decodes properly. 38 func TestHashEncodeDecodeZero(t *testing.T) { 39 codec := kbfscodec.NewMsgpack() 40 encodedH, err := codec.Encode(Hash{}) 41 require.NoError(t, err) 42 43 expectedEncodedH := []byte{0xc0} 44 require.Equal(t, expectedEncodedH, encodedH) 45 46 var h Hash 47 err = codec.Decode(encodedH, &h) 48 require.NoError(t, err) 49 50 require.Equal(t, Hash{}, h) 51 } 52 53 // Make sure that default hash gives a valid hash that verifies. 54 func TestDefaultHash(t *testing.T) { 55 data := []byte{1, 2, 3, 4, 5} 56 h, err := DefaultHash(data) 57 require.NoError(t, err) 58 59 require.True(t, h.IsValid()) 60 61 err = h.Verify(data) 62 require.NoError(t, err) 63 } 64 65 // hashFromRawNoCheck() is like HashFromRaw() except it doesn't check 66 // validity. 67 func hashFromRawNoCheck(hashType HashType, rawHash []byte) Hash { 68 return Hash{string(append([]byte{byte(hashType)}, rawHash...))} 69 } 70 71 // Make sure Hash.IsValid() fails properly. 72 func TestHashIsValid(t *testing.T) { 73 data := []byte{1, 2, 3, 4, 5} 74 validH, err := DefaultHash(data) 75 require.NoError(t, err) 76 77 // Zero hash. 78 require.False(t, (Hash{}).IsValid()) 79 80 var smallH Hash 81 smallH.h = validH.h[:MinHashByteLength-1] 82 require.False(t, smallH.IsValid()) 83 84 var largeH Hash 85 padding := make([]byte, MaxHashByteLength-len(validH.h)+1) 86 largeH.h = string(append([]byte(validH.h), padding...)) 87 require.False(t, largeH.IsValid()) 88 89 invalidH := hashFromRawNoCheck(InvalidHash, validH.hashData()) 90 require.False(t, invalidH.IsValid()) 91 92 // A hash with an unknown version is still valid. 93 unknownH := hashFromRawNoCheck(validH.hashType()+1, validH.hashData()) 94 require.True(t, unknownH.IsValid()) 95 } 96 97 // Make sure Hash.Verify() fails properly. 98 func TestHashVerify(t *testing.T) { 99 data := []byte{1, 2, 3, 4, 5} 100 101 // Zero (invalid) hash. 102 err := (Hash{}).Verify(data) 103 require.Equal(t, InvalidHashError{Hash{}}, errors.Cause(err)) 104 105 validH, err := DefaultHash(data) 106 require.NoError(t, err) 107 108 corruptData := make([]byte, len(data)) 109 copy(corruptData, data) 110 corruptData[0] ^= 1 111 err = validH.Verify(corruptData) 112 require.IsType(t, HashMismatchError{}, errors.Cause(err)) 113 114 invalidH := hashFromRawNoCheck(InvalidHash, validH.hashData()) 115 err = invalidH.Verify(data) 116 require.Equal(t, InvalidHashError{invalidH}, errors.Cause(err)) 117 118 // v2 should verify the same way as v1. 119 v2ValidH := hashFromRawNoCheck(SHA256HashV2, validH.hashData()) 120 err = v2ValidH.Verify(data) 121 require.NoError(t, err) 122 123 unknownType := validH.hashType() + 2 124 unknownH := hashFromRawNoCheck(unknownType, validH.hashData()) 125 err = unknownH.Verify(data) 126 require.Equal(t, UnknownHashTypeError{unknownType}, errors.Cause(err)) 127 128 hashData := validH.hashData() 129 hashData[0] ^= 1 130 corruptH := hashFromRawNoCheck(validH.hashType(), hashData) 131 err = corruptH.Verify(data) 132 require.IsType(t, HashMismatchError{}, errors.Cause(err)) 133 } 134 135 // Make sure HMAC encodes and decodes properly with minimal overhead. 136 func TestHMACEncodeDecode(t *testing.T) { 137 codec := kbfscodec.NewMsgpack() 138 hmac, err := DefaultHMAC([]byte{1}, []byte{2}) 139 require.NoError(t, err) 140 141 encodedHMAC, err := codec.Encode(hmac) 142 require.NoError(t, err) 143 144 // See 145 // https://github.com/msgpack/msgpack/blob/master/spec.md#formats-bin 146 // for why there are two bytes of overhead. 147 const overhead = 2 148 require.Equal(t, DefaultHashByteLength+overhead, len(encodedHMAC)) 149 150 var hmac2 HMAC 151 err = codec.Decode(encodedHMAC, &hmac2) 152 require.NoError(t, err) 153 154 require.Equal(t, hmac, hmac2) 155 } 156 157 // Make sure the zero Hash value encodes and decodes properly. 158 func TestHMACEncodeDecodeZero(t *testing.T) { 159 codec := kbfscodec.NewMsgpack() 160 encodedHMAC, err := codec.Encode(HMAC{}) 161 require.NoError(t, err) 162 163 expectedEncodedHMAC := []byte{0xc0} 164 require.Equal(t, expectedEncodedHMAC, encodedHMAC) 165 166 var hmac HMAC 167 err = codec.Decode(encodedHMAC, &hmac) 168 require.NoError(t, err) 169 170 require.Equal(t, HMAC{}, hmac) 171 } 172 173 // Make sure that default HMAC gives a valid HMAC that verifies. 174 func TestDefaultHMAC(t *testing.T) { 175 key := []byte{1, 2} 176 data := []byte{1, 2, 3, 4, 5} 177 hmac, err := DefaultHMAC(key, data) 178 require.NoError(t, err) 179 180 require.True(t, hmac.IsValid()) 181 182 err = hmac.Verify(key, data) 183 require.NoError(t, err) 184 } 185 186 // No need to test HMAC.IsValid(). 187 188 // hmacFromRawNoCheck() is like HmacFromRaw() except it doesn't check 189 // validity. 190 func hmacFromRawNoCheck(hashType HashType, rawHash []byte) HMAC { 191 h := hashFromRawNoCheck(hashType, rawHash) 192 return HMAC{h} 193 } 194 195 // Make sure HMAC.Verify() fails properly. 196 func TestVerify(t *testing.T) { 197 key := []byte{1, 2} 198 data := []byte{1, 2, 3, 4, 5} 199 200 // Zero (invalid) HMAC. 201 err := (HMAC{}).Verify(key, data) 202 require.Equal(t, InvalidHashError{Hash{}}, errors.Cause(err)) 203 204 validHMAC, err := DefaultHMAC(key, data) 205 require.NoError(t, errors.Cause(err)) 206 207 corruptKey := make([]byte, len(key)) 208 copy(corruptKey, key) 209 corruptKey[0] ^= 1 210 err = validHMAC.Verify(corruptKey, data) 211 require.IsType(t, HashMismatchError{}, errors.Cause(err)) 212 213 corruptData := make([]byte, len(data)) 214 copy(corruptData, data) 215 corruptData[0] ^= 1 216 err = validHMAC.Verify(key, corruptData) 217 require.IsType(t, HashMismatchError{}, errors.Cause(err)) 218 219 invalidHMAC := hmacFromRawNoCheck(InvalidHash, validHMAC.hashData()) 220 err = invalidHMAC.Verify(key, data) 221 require.Equal(t, InvalidHashError{invalidHMAC.h}, errors.Cause(err)) 222 223 unknownType := validHMAC.hashType() + 1 224 unknownHMAC := hmacFromRawNoCheck(unknownType, validHMAC.hashData()) 225 err = unknownHMAC.Verify(key, data) 226 require.Equal(t, UnknownHashTypeError{unknownType}, errors.Cause(err)) 227 228 hashData := validHMAC.hashData() 229 hashData[0] ^= 1 230 corruptHMAC := hmacFromRawNoCheck(validHMAC.hashType(), hashData) 231 err = corruptHMAC.Verify(key, data) 232 require.IsType(t, HashMismatchError{}, errors.Cause(err)) 233 }