Files
crypto/wasm/verifier_test.go

227 lines
5.7 KiB
Go

package wasm
import (
"crypto/sha256"
"encoding/hex"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHashVerifier_ComputeHash(t *testing.T) {
verifier := NewHashVerifier()
testCases := []struct {
name string
input []byte
expected string
}{
{
name: "empty input",
input: []byte{},
expected: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
},
{
name: "simple wasm header",
input: []byte{0x00, 0x61, 0x73, 0x6d}, // \0asm
expected: "cd5d4935a48c0672cb06407bb443bc0087aff947c6b864bac886982c73b3027f",
},
{
name: "test module",
input: []byte("test wasm module content"),
expected: "945acabcfc93e347e8c08ea44afd3122670f04a89f9a0a0a5ce16ab849bbac06",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
hash := verifier.ComputeHash(tc.input)
assert.Equal(t, tc.expected, hash)
})
}
}
func TestHashVerifier_TrustedHashes(t *testing.T) {
verifier := NewHashVerifier()
// Add trusted hash
moduleName := "test-module"
trustedHash := "abc123def456"
verifier.AddTrustedHash(moduleName, trustedHash)
// Retrieve trusted hash
hash, exists := verifier.GetTrustedHash(moduleName)
assert.True(t, exists)
assert.Equal(t, trustedHash, hash)
// Non-existent module
_, exists = verifier.GetTrustedHash("non-existent")
assert.False(t, exists)
// Clear hashes
verifier.ClearTrustedHashes()
_, exists = verifier.GetTrustedHash(moduleName)
assert.False(t, exists)
}
func TestHashVerifier_VerifyHash(t *testing.T) {
verifier := NewHashVerifier()
// Test data
wasmBytes := []byte("test wasm module")
expectedHash := verifier.ComputeHash(wasmBytes)
moduleName := "test-module"
// Test missing trusted hash
err := verifier.VerifyHash(moduleName, wasmBytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "no trusted hash found")
// Add trusted hash
verifier.AddTrustedHash(moduleName, expectedHash)
// Test successful verification
err = verifier.VerifyHash(moduleName, wasmBytes)
assert.NoError(t, err)
// Test failed verification
verifier.AddTrustedHash(moduleName, "wrong-hash")
err = verifier.VerifyHash(moduleName, wasmBytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "hash verification failed")
}
func TestHashVerifier_VerifyHashWithFallback(t *testing.T) {
verifier := NewHashVerifier()
wasmBytes := []byte("test wasm module")
actualHash := verifier.ComputeHash(wasmBytes)
moduleName := "test-module"
// Test with fallback hashes
fallbackHashes := []string{
"wrong-hash-1",
actualHash,
"wrong-hash-2",
}
err := verifier.VerifyHashWithFallback(moduleName, wasmBytes, fallbackHashes)
assert.NoError(t, err)
// Verify that the hash was added as trusted
trustedHash, exists := verifier.GetTrustedHash(moduleName)
assert.True(t, exists)
assert.Equal(t, actualHash, trustedHash)
// Test with no matching fallback
fallbackHashes = []string{"wrong-1", "wrong-2"}
verifier.ClearTrustedHashes()
err = verifier.VerifyHashWithFallback(moduleName, wasmBytes, fallbackHashes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "not in trusted set")
}
func TestHashChain(t *testing.T) {
chain := NewHashChain()
// Add entries
timestamp1 := time.Now().Unix()
err := chain.AddEntry("v1.0.0", "hash1", timestamp1)
require.NoError(t, err)
timestamp2 := time.Now().Unix()
err = chain.AddEntry("v1.0.1", "hash2", timestamp2)
require.NoError(t, err)
timestamp3 := time.Now().Unix()
err = chain.AddEntry("v1.0.2", "hash3", timestamp3)
require.NoError(t, err)
// Verify chain integrity
err = chain.VerifyChain()
assert.NoError(t, err)
// Get latest entry
latest, err := chain.GetLatestEntry()
require.NoError(t, err)
assert.Equal(t, "v1.0.2", latest.Version)
assert.Equal(t, "hash3", latest.Hash)
assert.Equal(t, "hash2", latest.PreviousHash)
}
func TestHashChain_BrokenChain(t *testing.T) {
chain := NewHashChain()
// Manually create a broken chain
chain.chain = []HashEntry{
{Version: "v1", Hash: "hash1", PreviousHash: ""},
{Version: "v2", Hash: "hash2", PreviousHash: "hash1"},
{Version: "v3", Hash: "hash3", PreviousHash: "wrong-hash"}, // Broken link
}
err := chain.VerifyChain()
assert.Error(t, err)
assert.Contains(t, err.Error(), "hash chain broken")
}
func TestSecurityPolicy(t *testing.T) {
policy := DefaultSecurityPolicy()
// Test size validation
smallModule := make([]byte, 1024)
err := policy.Validate(smallModule)
assert.NoError(t, err)
// Test oversized module
largeModule := make([]byte, 11*1024*1024)
err = policy.Validate(largeModule)
assert.Error(t, err)
assert.Contains(t, err.Error(), "exceeds maximum allowed size")
}
func TestVerificationError(t *testing.T) {
err := &VerificationError{
Module: "test.wasm",
ExpectedHash: "expected123",
ActualHash: "actual456",
Reason: "hash mismatch",
}
errStr := err.Error()
assert.Contains(t, errStr, "test.wasm")
assert.Contains(t, errStr, "hash mismatch")
assert.Contains(t, errStr, "expected123")
assert.Contains(t, errStr, "actual456")
}
func BenchmarkComputeHash(b *testing.B) {
verifier := NewHashVerifier()
data := make([]byte, 1024*1024) // 1MB
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = verifier.ComputeHash(data)
}
}
func BenchmarkVerifyHash(b *testing.B) {
verifier := NewHashVerifier()
data := make([]byte, 1024*1024) // 1MB
hash := verifier.ComputeHash(data)
verifier.AddTrustedHash("bench-module", hash)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = verifier.VerifyHash("bench-module", data)
}
}
// Helper function to compute SHA256 hash for testing
func computeSHA256(data []byte) string {
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:])
}