214 lines
6.2 KiB
Go
214 lines
6.2 KiB
Go
package pkg_test
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/rwadurian/mpc-system/pkg/crypto"
|
|
)
|
|
|
|
func TestGenerateRandomBytes(t *testing.T) {
|
|
t.Run("should generate random bytes of correct length", func(t *testing.T) {
|
|
lengths := []int{16, 32, 64, 128}
|
|
|
|
for _, length := range lengths {
|
|
bytes, err := crypto.GenerateRandomBytes(length)
|
|
require.NoError(t, err)
|
|
assert.Len(t, bytes, length)
|
|
}
|
|
})
|
|
|
|
t.Run("should generate different bytes each time", func(t *testing.T) {
|
|
bytes1, _ := crypto.GenerateRandomBytes(32)
|
|
bytes2, _ := crypto.GenerateRandomBytes(32)
|
|
|
|
assert.NotEqual(t, bytes1, bytes2)
|
|
})
|
|
}
|
|
|
|
func TestHashMessage(t *testing.T) {
|
|
t.Run("should hash message consistently", func(t *testing.T) {
|
|
message := []byte("test message")
|
|
|
|
hash1 := crypto.HashMessage(message)
|
|
hash2 := crypto.HashMessage(message)
|
|
|
|
assert.Equal(t, hash1, hash2)
|
|
assert.Len(t, hash1, 32) // SHA-256 produces 32 bytes
|
|
})
|
|
|
|
t.Run("should produce different hashes for different messages", func(t *testing.T) {
|
|
hash1 := crypto.HashMessage([]byte("message1"))
|
|
hash2 := crypto.HashMessage([]byte("message2"))
|
|
|
|
assert.NotEqual(t, hash1, hash2)
|
|
})
|
|
}
|
|
|
|
func TestEncryptDecrypt(t *testing.T) {
|
|
t.Run("should encrypt and decrypt data successfully", func(t *testing.T) {
|
|
key := make([]byte, 32)
|
|
rand.Read(key)
|
|
plaintext := []byte("secret data to encrypt")
|
|
|
|
ciphertext, err := crypto.Encrypt(key, plaintext)
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, plaintext, ciphertext)
|
|
|
|
decrypted, err := crypto.Decrypt(key, ciphertext)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, plaintext, decrypted)
|
|
})
|
|
|
|
t.Run("should fail decryption with wrong key", func(t *testing.T) {
|
|
key1 := make([]byte, 32)
|
|
key2 := make([]byte, 32)
|
|
rand.Read(key1)
|
|
rand.Read(key2)
|
|
|
|
plaintext := []byte("secret data")
|
|
ciphertext, _ := crypto.Encrypt(key1, plaintext)
|
|
|
|
_, err := crypto.Decrypt(key2, ciphertext)
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("should produce different ciphertext for same plaintext", func(t *testing.T) {
|
|
key := make([]byte, 32)
|
|
rand.Read(key)
|
|
plaintext := []byte("secret data")
|
|
|
|
ciphertext1, _ := crypto.Encrypt(key, plaintext)
|
|
ciphertext2, _ := crypto.Encrypt(key, plaintext)
|
|
|
|
// Due to random nonce, ciphertexts should be different
|
|
assert.NotEqual(t, ciphertext1, ciphertext2)
|
|
})
|
|
}
|
|
|
|
func TestDeriveKey(t *testing.T) {
|
|
t.Run("should derive key consistently", func(t *testing.T) {
|
|
secret := []byte("master secret")
|
|
salt := []byte("random salt")
|
|
|
|
key1, err := crypto.DeriveKey(secret, salt, 32)
|
|
require.NoError(t, err)
|
|
|
|
key2, err := crypto.DeriveKey(secret, salt, 32)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, key1, key2)
|
|
assert.Len(t, key1, 32)
|
|
})
|
|
|
|
t.Run("should derive different keys with different salts", func(t *testing.T) {
|
|
secret := []byte("master secret")
|
|
|
|
key1, _ := crypto.DeriveKey(secret, []byte("salt1"), 32)
|
|
key2, _ := crypto.DeriveKey(secret, []byte("salt2"), 32)
|
|
|
|
assert.NotEqual(t, key1, key2)
|
|
})
|
|
}
|
|
|
|
func TestSignAndVerify(t *testing.T) {
|
|
t.Run("should sign and verify successfully", func(t *testing.T) {
|
|
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
require.NoError(t, err)
|
|
|
|
message := []byte("message to sign")
|
|
signature, err := crypto.SignMessage(privateKey, message)
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, signature)
|
|
|
|
// Hash the message for verification (SignMessage internally hashes)
|
|
messageHash := crypto.HashMessage(message)
|
|
valid := crypto.VerifySignature(&privateKey.PublicKey, messageHash, signature)
|
|
assert.True(t, valid)
|
|
})
|
|
|
|
t.Run("should fail verification with wrong message", func(t *testing.T) {
|
|
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
|
|
signature, _ := crypto.SignMessage(privateKey, []byte("original message"))
|
|
|
|
wrongHash := crypto.HashMessage([]byte("different message"))
|
|
valid := crypto.VerifySignature(&privateKey.PublicKey, wrongHash, signature)
|
|
assert.False(t, valid)
|
|
})
|
|
|
|
t.Run("should fail verification with wrong public key", func(t *testing.T) {
|
|
privateKey1, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
privateKey2, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
|
|
message := []byte("message")
|
|
signature, _ := crypto.SignMessage(privateKey1, message)
|
|
|
|
messageHash := crypto.HashMessage(message)
|
|
valid := crypto.VerifySignature(&privateKey2.PublicKey, messageHash, signature)
|
|
assert.False(t, valid)
|
|
})
|
|
}
|
|
|
|
func TestEncodeDecodeHex(t *testing.T) {
|
|
t.Run("should encode and decode hex successfully", func(t *testing.T) {
|
|
original := []byte("test data")
|
|
|
|
encoded := crypto.EncodeToHex(original)
|
|
assert.NotEmpty(t, encoded)
|
|
|
|
decoded, err := crypto.DecodeFromHex(encoded)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, original, decoded)
|
|
})
|
|
|
|
t.Run("should fail to decode invalid hex", func(t *testing.T) {
|
|
_, err := crypto.DecodeFromHex("invalid-hex-string!")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestPublicKeyMarshaling(t *testing.T) {
|
|
t.Run("should marshal and unmarshal public key", func(t *testing.T) {
|
|
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
|
|
encoded := crypto.MarshalPublicKey(&privateKey.PublicKey)
|
|
assert.NotEmpty(t, encoded)
|
|
|
|
decoded, err := crypto.ParsePublicKey(encoded)
|
|
require.NoError(t, err)
|
|
|
|
// Verify keys are equal by comparing coordinates
|
|
assert.Equal(t, privateKey.PublicKey.X.Bytes(), decoded.X.Bytes())
|
|
assert.Equal(t, privateKey.PublicKey.Y.Bytes(), decoded.Y.Bytes())
|
|
})
|
|
}
|
|
|
|
func TestCompareBytes(t *testing.T) {
|
|
t.Run("should return true for equal byte slices", func(t *testing.T) {
|
|
a := []byte("test data")
|
|
b := []byte("test data")
|
|
|
|
assert.True(t, crypto.CompareBytes(a, b))
|
|
})
|
|
|
|
t.Run("should return false for different byte slices", func(t *testing.T) {
|
|
a := []byte("test data 1")
|
|
b := []byte("test data 2")
|
|
|
|
assert.False(t, crypto.CompareBytes(a, b))
|
|
})
|
|
|
|
t.Run("should return false for different length byte slices", func(t *testing.T) {
|
|
a := []byte("short")
|
|
b := []byte("longer string")
|
|
|
|
assert.False(t, crypto.CompareBytes(a, b))
|
|
})
|
|
}
|