Files
netbird/client/internal/updatemanager/reposign/signature_test.go
2025-12-19 19:57:39 +01:00

278 lines
6.7 KiB
Go

package reposign
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseSignature_Valid(t *testing.T) {
timestamp := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
keyID, err := ParseKeyID("0123456789abcdef")
require.NoError(t, err)
signatureData := []byte{0x01, 0x02, 0x03, 0x04}
jsonData, err := json.Marshal(Signature{
Signature: signatureData,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
})
require.NoError(t, err)
sig, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.Equal(t, signatureData, sig.Signature)
assert.Equal(t, timestamp.Unix(), sig.Timestamp.Unix())
assert.Equal(t, keyID, sig.KeyID)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.Equal(t, "blake2s", sig.HashAlgo)
}
func TestParseSignature_InvalidJSON(t *testing.T) {
invalidJSON := []byte(`{invalid json}`)
sig, err := ParseSignature(invalidJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestParseSignature_EmptyData(t *testing.T) {
emptyJSON := []byte(`{}`)
sig, err := ParseSignature(emptyJSON)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.Empty(t, sig.Signature)
assert.True(t, sig.Timestamp.IsZero())
assert.Equal(t, KeyID{}, sig.KeyID)
assert.Empty(t, sig.Algorithm)
assert.Empty(t, sig.HashAlgo)
}
func TestParseSignature_MissingFields(t *testing.T) {
// JSON with only some fields
partialJSON := []byte(`{
"signature": "AQIDBA==",
"algorithm": "ed25519"
}`)
sig, err := ParseSignature(partialJSON)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.NotEmpty(t, sig.Signature)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.True(t, sig.Timestamp.IsZero())
}
func TestSignature_MarshalUnmarshal_Roundtrip(t *testing.T) {
timestamp := time.Date(2024, 6, 20, 14, 45, 30, 0, time.UTC)
keyID, err := ParseKeyID("fedcba9876543210")
require.NoError(t, err)
original := Signature{
Signature: []byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe},
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "sha512",
}
// Marshal
jsonData, err := json.Marshal(original)
require.NoError(t, err)
// Unmarshal
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
// Verify
assert.Equal(t, original.Signature, parsed.Signature)
assert.Equal(t, original.Timestamp.Unix(), parsed.Timestamp.Unix())
assert.Equal(t, original.KeyID, parsed.KeyID)
assert.Equal(t, original.Algorithm, parsed.Algorithm)
assert.Equal(t, original.HashAlgo, parsed.HashAlgo)
}
func TestSignature_NilSignatureBytes(t *testing.T) {
timestamp := time.Now().UTC()
keyID, err := ParseKeyID("0011223344556677")
require.NoError(t, err)
sig := Signature{
Signature: nil,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Nil(t, parsed.Signature)
}
func TestSignature_LargeSignature(t *testing.T) {
timestamp := time.Now().UTC()
keyID, err := ParseKeyID("aabbccddeeff0011")
require.NoError(t, err)
// Create a large signature (64 bytes for ed25519)
largeSignature := make([]byte, 64)
for i := range largeSignature {
largeSignature[i] = byte(i)
}
sig := Signature{
Signature: largeSignature,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, largeSignature, parsed.Signature)
}
func TestSignature_WithDifferentHashAlgorithms(t *testing.T) {
tests := []struct {
name string
hashAlgo string
}{
{"blake2s", "blake2s"},
{"sha512", "sha512"},
{"sha256", "sha256"},
{"empty", ""},
}
keyID, err := ParseKeyID("1122334455667788")
require.NoError(t, err)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sig := Signature{
Signature: []byte{0x01, 0x02},
Timestamp: time.Now().UTC(),
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: tt.hashAlgo,
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, tt.hashAlgo, parsed.HashAlgo)
})
}
}
func TestSignature_TimestampPrecision(t *testing.T) {
// Test that timestamp preserves precision through JSON marshaling
timestamp := time.Date(2024, 3, 15, 10, 30, 45, 123456789, time.UTC)
keyID, err := ParseKeyID("8877665544332211")
require.NoError(t, err)
sig := Signature{
Signature: []byte{0xaa, 0xbb},
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
// JSON timestamps typically have second or millisecond precision
// so we check that at least seconds match
assert.Equal(t, timestamp.Unix(), parsed.Timestamp.Unix())
}
func TestParseSignature_MalformedKeyID(t *testing.T) {
// Test with a malformed KeyID field
malformedJSON := []byte(`{
"signature": "AQID",
"timestamp": "2024-01-15T10:30:00Z",
"key_id": "invalid_keyid_format",
"algorithm": "ed25519",
"hash_algo": "blake2s"
}`)
// This should fail since "invalid_keyid_format" is not a valid KeyID
sig, err := ParseSignature(malformedJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestParseSignature_InvalidTimestamp(t *testing.T) {
// Test with an invalid timestamp format
invalidTimestampJSON := []byte(`{
"signature": "AQID",
"timestamp": "not-a-timestamp",
"key_id": "0123456789abcdef",
"algorithm": "ed25519",
"hash_algo": "blake2s"
}`)
sig, err := ParseSignature(invalidTimestampJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestSignature_ZeroKeyID(t *testing.T) {
// Test with a zero KeyID
sig := Signature{
Signature: []byte{0x01, 0x02, 0x03},
Timestamp: time.Now().UTC(),
KeyID: KeyID{},
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, KeyID{}, parsed.KeyID)
}
func TestParseSignature_ExtraFields(t *testing.T) {
// JSON with extra fields that should be ignored
jsonWithExtra := []byte(`{
"signature": "AQIDBA==",
"timestamp": "2024-01-15T10:30:00Z",
"key_id": "0123456789abcdef",
"algorithm": "ed25519",
"hash_algo": "blake2s",
"extra_field": "should be ignored",
"another_extra": 12345
}`)
sig, err := ParseSignature(jsonWithExtra)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.NotEmpty(t, sig.Signature)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.Equal(t, "blake2s", sig.HashAlgo)
}