package namespace import ( "bytes" "testing" "crypto/ed25519" "github.com/system-transparency/stfe/namespace/testdata" ) func TestNewNamespaceEd25519V1(t *testing.T) { for _, table := range []struct { description string vk []byte wantErr bool }{ { description: "invalid", vk: append(testdata.Ed25519Vk, 0x00), wantErr: true, }, { description: "valid", vk: testdata.Ed25519Vk, }, } { n, err := NewNamespaceEd25519V1(table.vk) if got, want := err != nil, table.wantErr; got != want { t.Errorf("got error %v but wanted %v in test %q: %v", got, want, table.description, err) } if err != nil { continue } if got, want := n.Format, NamespaceFormatEd25519V1; got != want { t.Errorf("got namespace format %v but wanted %v in test %q", got, want, table.description) continue } if got, want := n.NamespaceEd25519V1.Namespace, table.vk; !bytes.Equal(got, want) { t.Errorf("got namespace %X but wanted %X in test %q", got, want, table.description) } } } func TestVerify(t *testing.T) { testMsg := []byte("msg") for _, table := range []struct { description string namespace *Namespace msg, sig []byte wantErr bool }{ { description: "invalid: unsupported namespace", namespace: &Namespace{Format: NamespaceFormatReserved}, msg: testMsg, sig: []byte("sig"), wantErr: true, }, { description: "invalid: bad ed25519 verification key", namespace: mustNewNamespaceEd25519V1(t, testdata.Ed25519Sk[:32]), msg: testMsg, sig: ed25519.Sign(ed25519.PrivateKey(testdata.Ed25519Sk), testMsg), wantErr: true, }, { description: "invalid: ed25519 signature is not over message", namespace: mustNewNamespaceEd25519V1(t, testdata.Ed25519Vk), msg: append(testMsg, 0x00), sig: ed25519.Sign(ed25519.PrivateKey(testdata.Ed25519Sk), testMsg), wantErr: true, }, { description: "valid: ed25519", namespace: mustNewNamespaceEd25519V1(t, testdata.Ed25519Vk), msg: testMsg, sig: ed25519.Sign(ed25519.PrivateKey(testdata.Ed25519Sk), testMsg), }, } { err := table.namespace.Verify(table.msg, table.sig) if got, want := err != nil, table.wantErr; got != want { t.Errorf("got error=%v but wanted %v in test %q: %v", got, want, table.description, err) } } } func TestMarshal(t *testing.T) { for _, table := range []struct { description string namespace *Namespace wantErr bool wantBytes []byte }{ { description: "invalid ed25519: namespace size too small", namespace: &Namespace{ Format: NamespaceFormatEd25519V1, NamespaceEd25519V1: &NamespaceEd25519V1{ Namespace: testdata.Ed25519Vk[:len(testdata.Ed25519Vk)-1], }, }, wantErr: true, }, { description: "invalid ed25519: namespace size too large", namespace: &Namespace{ Format: NamespaceFormatEd25519V1, NamespaceEd25519V1: &NamespaceEd25519V1{ Namespace: append(testdata.Ed25519Vk, 0x00), }, }, wantErr: true, }, { description: "valid: ed25519", namespace: mustNewNamespaceEd25519V1(t, testdata.Ed25519Vk), // TODO: wantBytes }, } { _, err := table.namespace.Marshal() if got, want := err != nil, table.wantErr; got != want { t.Errorf("got error %v but wanted %v in test %q: %v", got, want, table.description, err) } if err != nil { continue } // TODO: add check that we got the bytes we wanted also } } func TestUnmarshal(t *testing.T) { // TODO } func TestNewNamespacePool(t *testing.T) { ns1, _ := NewNamespaceEd25519V1(testdata.Ed25519Vk) ns2, _ := NewNamespaceEd25519V1(make([]byte, 32)) nsr := &Namespace{Format: NamespaceFormatReserved} for _, table := range []struct { description string namespaces []*Namespace wantErr bool }{ { description: "invalid: duplicate namespace", namespaces: []*Namespace{ns1, ns1, ns2}, wantErr: true, }, { description: "invalid: namespace without key", namespaces: []*Namespace{ns1, nsr, ns2}, wantErr: true, }, { description: "valid: empty", namespaces: []*Namespace{}, }, { description: "valid: one namespace", namespaces: []*Namespace{ns1}, }, { description: "valid: two namespaces", namespaces: []*Namespace{ns1, ns2}, }, } { _, err := NewNamespacePool(table.namespaces) if got, want := err != nil, table.wantErr; got != want { t.Errorf("got error %v but wanted %v in test %q: %v", got, want, table.description, err) } } } func TestFind(t *testing.T) { ns1 := mustNewNamespaceEd25519V1(t, testdata.Ed25519Vk) ns2 := mustNewNamespaceEd25519V1(t, make([]byte, 32)) pool, _ := NewNamespacePool(nil) _, got := pool.Find(ns1) if want := false; got != want { t.Errorf("got %v but wanted %v in test %q", got, want, "empty pool") } pool, _ = NewNamespacePool([]*Namespace{ns1}) _, got = pool.Find(ns1) if want := true; got != want { t.Errorf("got %v but wanted %v in test %q", got, want, "non-empty pool: looking for member") } _, got = pool.Find(ns2) if want := false; got != want { t.Errorf("got %v but wanted %v in test %q", got, want, "non-empty pool: looking for non-member") } } func TestList(t *testing.T) { ns1 := mustNewNamespaceEd25519V1(t, testdata.Ed25519Vk) ns2 := mustNewNamespaceEd25519V1(t, make([]byte, 32)) namespaces := []*Namespace{ns1, ns2} pool, _ := NewNamespacePool(namespaces) l1 := pool.List() if got, want := len(l1), len(namespaces); got != want { t.Errorf("got len %v but wanted %v", got, want) } l1[0] = ns2 l2 := pool.List() if bytes.Equal(l1[0].NamespaceEd25519V1.Namespace, l2[0].NamespaceEd25519V1.Namespace) { t.Errorf("returned list is not a copy") } } func mustNewNamespaceEd25519V1(t *testing.T, vk []byte) *Namespace { namespace, err := NewNamespaceEd25519V1(vk) if err != nil { t.Fatalf("must make ed25519 namespace: %v", err) } return namespace }