github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/crypto/hash_test.go (about)

     1  package crypto_test
     2  
     3  import (
     4  	"crypto/rand"
     5  	"testing"
     6  
     7  	"crypto/sha256"
     8  	"crypto/sha512"
     9  
    10  	"github.com/onflow/crypto/hash"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	"golang.org/x/crypto/sha3"
    14  
    15  	"github.com/onflow/flow-go/fvm/crypto"
    16  	"github.com/onflow/flow-go/model/flow"
    17  )
    18  
    19  // TestPrefixedHash is a specific test for prefixed hashing
    20  func TestPrefixedHash(t *testing.T) {
    21  
    22  	hashingAlgoToTestingAlgo := map[hash.HashingAlgorithm]func([]byte) []byte{
    23  		hash.SHA2_256: func(data []byte) []byte {
    24  			h := sha256.Sum256(data)
    25  			return h[:]
    26  		},
    27  		hash.SHA3_256: func(data []byte) []byte {
    28  			h := sha3.Sum256(data)
    29  			return h[:]
    30  		},
    31  		hash.SHA2_384: func(data []byte) []byte {
    32  			h := sha512.Sum384(data)
    33  			return h[:]
    34  		},
    35  		hash.SHA3_384: func(data []byte) []byte {
    36  			h := sha3.Sum384(data)
    37  			return h[:]
    38  		},
    39  		hash.Keccak_256: func(data []byte) []byte {
    40  			var output [hash.HashLenKeccak_256]byte
    41  			h := sha3.NewLegacyKeccak256()
    42  			h.Write(data)
    43  			return h.Sum(output[:0])[:]
    44  		},
    45  	}
    46  
    47  	for hashAlgo, testFunction := range hashingAlgoToTestingAlgo {
    48  		t.Run(hashAlgo.String()+" with a prefix", func(t *testing.T) {
    49  			for i := flow.DomainTagLength; i < 5000; i++ {
    50  				// first 32 bytes of data are the tag
    51  				data := make([]byte, i)
    52  				_, err := rand.Read(data)
    53  				require.NoError(t, err)
    54  				expected := testFunction(data)
    55  
    56  				tag := string(data[:flow.DomainTagLength])
    57  				message := data[flow.DomainTagLength:]
    58  				hasher, err := crypto.NewPrefixedHashing(hashAlgo, tag)
    59  				require.NoError(t, err)
    60  				h := hasher.ComputeHash(message)
    61  				assert.Equal(t, expected, []byte(h))
    62  			}
    63  		})
    64  
    65  		t.Run(hashAlgo.String()+" without a prefix", func(t *testing.T) {
    66  			for i := 0; i < 5000; i++ {
    67  				data := make([]byte, i)
    68  				_, err := rand.Read(data)
    69  				require.NoError(t, err)
    70  				expected := testFunction(data)
    71  
    72  				tag := ""
    73  				hasher, err := crypto.NewPrefixedHashing(hashAlgo, tag)
    74  				require.NoError(t, err)
    75  				h := hasher.ComputeHash(data)
    76  				assert.Equal(t, expected, []byte(h))
    77  			}
    78  		})
    79  
    80  		t.Run(hashAlgo.String()+" with tagged prefix", func(t *testing.T) {
    81  			data := make([]byte, 100) // data to hash
    82  			_, err := rand.Read(data)
    83  			require.NoError(t, err)
    84  			tag := "tag" // tag to be padded
    85  
    86  			hasher, err := crypto.NewPrefixedHashing(hashAlgo, tag)
    87  			require.NoError(t, err)
    88  			expected := hasher.ComputeHash(data)
    89  			for i := len(tag); i < flow.DomainTagLength; i++ {
    90  				paddedTag := make([]byte, i)
    91  				copy(paddedTag, tag)
    92  				paddedHasher, err := crypto.NewPrefixedHashing(hashAlgo, string(paddedTag))
    93  				require.NoError(t, err)
    94  				h := paddedHasher.ComputeHash(data)
    95  
    96  				assert.Equal(t, expected, h)
    97  			}
    98  		})
    99  	}
   100  
   101  	t.Run("non supported algorithm", func(t *testing.T) {
   102  		_, err := crypto.NewPrefixedHashing(hash.KMAC128, "")
   103  		require.Error(t, err)
   104  	})
   105  }