phase 3
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
package keypair_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"galaxy/core/keypair"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGenerateProducesIndependentCopies(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
priv, pub, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, priv, ed25519.PrivateKeySize)
|
||||
require.Len(t, pub, ed25519.PublicKeySize)
|
||||
|
||||
// Mutating the returned slices must not affect a fresh call.
|
||||
priv[0] ^= 0xFF
|
||||
pub[0] ^= 0xFF
|
||||
priv2, pub2, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
assert.NotEqual(t, priv[:8], priv2[:8])
|
||||
assert.NotEqual(t, pub[:8], pub2[:8])
|
||||
}
|
||||
|
||||
func TestGenerateIsDeterministicForFixedSeed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := bytes.Repeat([]byte{0x42}, ed25519.SeedSize)
|
||||
|
||||
priv1, pub1, err := keypair.Generate(bytes.NewReader(seed))
|
||||
require.NoError(t, err)
|
||||
priv2, pub2, err := keypair.Generate(bytes.NewReader(seed))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, priv1, priv2)
|
||||
assert.Equal(t, pub1, pub2)
|
||||
}
|
||||
|
||||
func TestGenerateRejectsNilReader(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, err := keypair.Generate(nil)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestSignRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
priv, pub, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
message := []byte("ui-core-roundtrip")
|
||||
signature, err := keypair.Sign(priv, message)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, signature, ed25519.SignatureSize)
|
||||
|
||||
assert.True(t, keypair.Verify(pub, message, signature))
|
||||
assert.False(t, keypair.Verify(pub, []byte("tampered"), signature))
|
||||
tampered := append([]byte(nil), signature...)
|
||||
tampered[0] ^= 0xFF
|
||||
assert.False(t, keypair.Verify(pub, message, tampered))
|
||||
}
|
||||
|
||||
func TestSignRejectsInvalidPrivateKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := keypair.Sign([]byte("short"), []byte("message"))
|
||||
require.ErrorIs(t, err, keypair.ErrInvalidPrivateKey)
|
||||
}
|
||||
|
||||
func TestVerifyRejectsInvalidLengths(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
priv, pub, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
signature, err := keypair.Sign(priv, []byte("message"))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.False(t, keypair.Verify(pub[:8], []byte("message"), signature))
|
||||
assert.False(t, keypair.Verify(pub, []byte("message"), signature[:8]))
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalPublicKeyRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, pub, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
encoded, err := keypair.MarshalPublicKey(pub)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, encoded)
|
||||
|
||||
// Encoding must be base64 StdEncoding to match docs/ARCHITECTURE.md §15.
|
||||
expected := base64.StdEncoding.EncodeToString(pub)
|
||||
assert.Equal(t, expected, encoded)
|
||||
|
||||
decoded, err := keypair.UnmarshalPublicKey(encoded)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, pub, decoded)
|
||||
}
|
||||
|
||||
func TestMarshalPublicKeyRejectsInvalidLength(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := keypair.MarshalPublicKey([]byte("short"))
|
||||
require.ErrorIs(t, err, keypair.ErrInvalidPublicKey)
|
||||
}
|
||||
|
||||
func TestUnmarshalPublicKeyRejectsBadEncoding(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := keypair.UnmarshalPublicKey("%%%not-base64%%%")
|
||||
require.ErrorIs(t, err, keypair.ErrInvalidPublicKeyEncoding)
|
||||
}
|
||||
|
||||
func TestUnmarshalPublicKeyRejectsWrongLength(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := keypair.UnmarshalPublicKey(base64.StdEncoding.EncodeToString([]byte("short")))
|
||||
require.ErrorIs(t, err, keypair.ErrInvalidPublicKey)
|
||||
}
|
||||
|
||||
func TestPublicKeyFromPrivate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
priv, pub, err := keypair.Generate(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
derived, err := keypair.PublicKeyFromPrivate(priv)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, pub, derived)
|
||||
|
||||
_, err = keypair.PublicKeyFromPrivate([]byte("short"))
|
||||
require.ErrorIs(t, err, keypair.ErrInvalidPrivateKey)
|
||||
}
|
||||
Reference in New Issue
Block a user