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/provider/provider_test.go

84 lines
3.9 KiB

package provider_test
import (
"bytes"
"errors"
"testing"
datekeys "g.activething.com/go/DateKeys"
"g.activething.com/go/DateKeys/internal/testkit"
"g.activething.com/go/DateKeys/profile"
"g.activething.com/go/DateKeys/provider"
)
func TestVerifyPublishedReleases(t *testing.T) {
p := profile.Quicknet()
for _, round := range testkit.Rounds {
if err := provider.Verify(p, provider.Condition{Round: round}, testkit.Release(round)); err != nil {
t.Fatalf("round %d: %v", round, err)
}
}
}
func TestVerifyRejects(t *testing.T) {
p := profile.Quicknet()
r1000, r1001 := testkit.Release(1000), testkit.Release(1001)
xPlusP, err := testkit.AddModulus(testkit.Release(testkit.XPlusPRound).Signature, 0)
if err != nil {
t.Fatal(err)
}
uncompressed := bytes.Clone(r1000.Signature)
uncompressed[0] &^= testkit.FlagCompressed
for _, tc := range []struct {
name string
cond uint64
rel provider.Release
want error
}{
// Spec §17: a valid signature of another round is not enough.
{"valid release of another round", 1000, r1001, datekeys.ErrRoundMismatch},
// Spec §63 step 10: the round is compared before the signature.
{"another round and a short signature", 1000, provider.Release{Round: 1001, Signature: r1001.Signature[:47]}, datekeys.ErrRoundMismatch},
// A signature of round 1001 relabelled as round 1000.
{"signature of another round relabelled", 1000, provider.Release{Round: 1000, Signature: r1001.Signature}, datekeys.ErrReleaseInvalid},
{"all-zero signature", 1000, provider.Release{Round: 1000, Signature: make([]byte, 48)}, datekeys.ErrReleaseInvalid},
{"flipped bit", 1000, provider.Release{Round: 1000, Signature: flip(r1000.Signature)}, datekeys.ErrReleaseInvalid},
{"short signature", 1000, provider.Release{Round: 1000, Signature: r1000.Signature[:47]}, datekeys.ErrReleaseInvalid},
{"G2-sized signature", 1000, provider.Release{Round: 1000, Signature: bytes.Repeat(r1000.Signature, 2)}, datekeys.ErrReleaseInvalid},
// Spec §12.2, §63 step 10: the canonical encoding of a point of G1
// other than the point at infinity. For a decoder that reduces x
// modulo p, x + p is the published signature of its round.
{"signature re-encoded with x + p", testkit.XPlusPRound, provider.Release{Round: testkit.XPlusPRound, Signature: xPlusP}, datekeys.ErrReleaseInvalid},
{"signature the point at infinity", 1000, provider.Release{Round: 1000, Signature: testkit.Infinity(48)}, datekeys.ErrReleaseInvalid},
{"infinity flag and a payload", 1000, provider.Release{Round: 1000, Signature: testkit.InfinityWithPayload(r1000.Signature)}, datekeys.ErrReleaseInvalid},
{"point at infinity with the sort flag", 1000, provider.Release{Round: 1000, Signature: testkit.Negated(testkit.Infinity(48))}, datekeys.ErrReleaseInvalid},
{"compression flag cleared", 1000, provider.Release{Round: 1000, Signature: uncompressed}, datekeys.ErrReleaseInvalid},
{"negated signature", 1000, provider.Release{Round: 1000, Signature: testkit.Negated(r1000.Signature)}, datekeys.ErrReleaseInvalid},
{"round zero", 0, provider.Release{Round: 0, Signature: r1000.Signature}, datekeys.ErrDateKeyInvalid},
{"round beyond the profile", p.MaxRound() + 1, provider.Release{Round: p.MaxRound() + 1, Signature: r1000.Signature}, datekeys.ErrDateKeyInvalid},
} {
t.Run(tc.name, func(t *testing.T) {
if err := provider.Verify(p, provider.Condition{Round: tc.cond}, tc.rel); !errors.Is(err, tc.want) {
t.Fatalf("got %v, want %v", err, tc.want)
}
})
}
}
func TestVerifyUsesThePinnedKeyOnly(t *testing.T) {
// A profile with another public key rejects the genuine signature.
p := profile.Quicknet()
p.PublicKey = append([]byte(nil), p.PublicKey...)
p.PublicKey[len(p.PublicKey)-1] ^= 1
err := provider.Verify(p, provider.Condition{Round: 1000}, testkit.Release(1000))
if err == nil {
t.Fatal("verified under a different key")
}
}
func flip(b []byte) []byte {
c := append([]byte(nil), b...)
c[10] ^= 0x01
return c
}

Powered by TurnKey Linux.