You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/internal/ed25519strict/ed25519strict_test.go

139 lines
4.7 KiB

package ed25519strict_test
import (
"crypto/ed25519"
"encoding/hex"
"slices"
"testing"
"g.activething.com/go/DateKeys/internal/ed25519strict"
"g.activething.com/go/DateKeys/internal/testkit"
)
// The table of the points of small order is what the arithmetic of testkit
// computes from the curve.
func TestSmallOrderTable(t *testing.T) {
var got, want [][32]byte
for _, p := range ed25519strict.SmallOrderPoints() {
got = append(got, p)
}
want = testkit.Ed25519Torsion()
cmp := func(a, b [32]byte) int { return slices.Compare(a[:], b[:]) }
slices.SortFunc(got, cmp)
slices.SortFunc(want, cmp)
if !slices.Equal(got, want) {
t.Fatalf("table %x, want %x", got, want)
}
}
func TestCanonical(t *testing.T) {
enc := func(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil || len(b) != 32 {
t.Fatalf("bad test encoding %s", s)
}
return b
}
for _, c := range []struct {
name string
a string
want bool
}{
{"y = 0", "0000000000000000000000000000000000000000000000000000000000000000", true},
{"y = 0, sign set: x is not 0", "0000000000000000000000000000000000000000000000000000000000000080", true},
{"y = 1", "0100000000000000000000000000000000000000000000000000000000000000", true},
{"y = 1, sign set: x is 0", "0100000000000000000000000000000000000000000000000000000000000080", false},
{"y = p - 1", "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", true},
{"y = p - 1, sign set", "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", false},
{"y = p", "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", false},
{"y = 2^255 - 1", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", false},
{"y = p - 2, sign set", "ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", true},
} {
if got := ed25519strict.Canonical(enc(c.a)); got != c.want {
t.Errorf("%s: Canonical = %v, want %v", c.name, got, c.want)
}
}
if ed25519strict.Canonical(make([]byte, 31)) || ed25519strict.SmallOrder(make([]byte, 33)) {
t.Error("a length other than 32 is accepted")
}
}
// OnCurve is true on the base point, on the points of small order and on
// keys of the CSPRNG, and false on y = 2, which has no x. Over the first 4096
// values of y it agrees with the square root of testkit.
func TestOnCurve(t *testing.T) {
base, _ := hex.DecodeString("5866666666666666666666666666666666666666666666666666666666666666")
if !ed25519strict.OnCurve(base) {
t.Error("the base point is not on the curve")
}
for _, p := range ed25519strict.SmallOrderPoints() {
if !ed25519strict.OnCurve(p[:]) {
t.Errorf("%x, of small order, is not on the curve", p)
}
}
for range 32 {
pub, _, _ := ed25519.GenerateKey(nil)
if !ed25519strict.OnCurve(pub) {
t.Fatalf("a key of the CSPRNG %x is not on the curve", pub)
}
}
two := make([]byte, 32)
two[0] = 2
if ed25519strict.OnCurve(two) || ed25519strict.OnCurve(make([]byte, 31)) {
t.Error("y = 2, or 31 bytes, is on the curve")
}
for y := range 4096 {
a := make([]byte, 32)
a[0], a[1] = byte(y), byte(y>>8)
if got, want := ed25519strict.OnCurve(a), testkit.Ed25519Decodes(a); got != want {
t.Fatalf("y = %d: OnCurve %v, the square root %v", y, got, want)
}
}
}
// crypto/ed25519 accepts any message with A = 01 00…00, R the identity and S
// = 0; Verify does not, nor a key or a signature of another length.
func TestVerifyRejectsWhatStdlibAccepts(t *testing.T) {
a := make([]byte, 32)
a[0] = 1
sig := make([]byte, 64)
sig[0] = 1
msg := []byte("anything")
if !ed25519.Verify(a, msg, sig) {
t.Fatal("crypto/ed25519 no longer accepts the forgery: review the comment of the package")
}
if ed25519strict.Verify(a, msg, sig) {
t.Error("Verify accepts a key of small order")
}
pub, priv, _ := ed25519.GenerateKey(nil)
good := ed25519.Sign(priv, msg)
if !ed25519strict.Verify(pub, msg, good) {
t.Error("Verify rejects a valid signature")
}
if ed25519strict.Verify(pub[:31], msg, good) || ed25519strict.Verify(pub, msg, good[:63]) {
t.Error("Verify accepts another length")
}
}
// The committed vectors give their result.
func TestVectors(t *testing.T) {
var f testkit.Ed25519StrictFile
if err := testkit.ReadJSON("../../testdata/vectors/ed25519_strict.json", &f); err != nil {
t.Fatal(err)
}
if len(f.Vectors) == 0 {
t.Fatal("no vectors")
}
for _, v := range f.Vectors {
msg, _ := hex.DecodeString(v.Message)
pub, _ := hex.DecodeString(v.PublicKey)
sig, _ := hex.DecodeString(v.Signature)
if got := ed25519strict.Verify(pub, msg, sig); got != v.Valid {
t.Errorf("%s: Verify = %v, want %v", v.Name, got, v.Valid)
}
if got := ed25519.Verify(pub, msg, sig); got != v.Stdlib {
t.Errorf("%s: crypto/ed25519 = %v, recorded %v", v.Name, got, v.Stdlib)
}
}
}

Powered by TurnKey Linux.