aboutsummaryrefslogtreecommitdiff
path: root/namespace
diff options
context:
space:
mode:
Diffstat (limited to 'namespace')
-rw-r--r--namespace/namespace.go150
-rw-r--r--namespace/namespace_test.go218
-rw-r--r--namespace/testdata/data.go21
3 files changed, 0 insertions, 389 deletions
diff --git a/namespace/namespace.go b/namespace/namespace.go
deleted file mode 100644
index f5c56cf..0000000
--- a/namespace/namespace.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Package namespace provides namespace functionality. A namespace refers to a
-// particular verification key and signing algorithm that can be serialized with
-// TLS 1.2 notation, see RFC 5246 (ยง4). Only Ed25519 is supported at this time.
-//
-// For example, this is how a serialized Ed25519 namespace looks like:
-//
-// 0 2 3 35 (byte index)
-// +----+-----------------------+
-// | 1 + 32 + Verification key +
-// +----+-----------------------+
-package namespace
-
-import (
- "fmt"
-
- "crypto/ed25519"
-
- "github.com/google/certificate-transparency-go/tls"
-)
-
-// NamespaceFormat defines a particular namespace type that is versioend
-type NamespaceFormat tls.Enum
-
-const (
- NamespaceFormatReserved NamespaceFormat = 0
- NamespaceFormatEd25519V1 NamespaceFormat = 1
-)
-
-// Namespace references a versioned namespace based on a given format specifier
-type Namespace struct {
- Format NamespaceFormat `tls:"maxval:65535"`
- NamespaceEd25519V1 *NamespaceEd25519V1 `tls:"selector:Format,val:1"`
-}
-
-// NamespaceEd25519V1 uses an Ed25519 verification key as namespace. Encoding,
-// signing, and verification operations are defined by RFC 8032.
-type NamespaceEd25519V1 struct {
- Namespace []byte `tls:"minlen:32,maxlen:32"`
-}
-
-// String returns a human-readable representation of a namespace.
-func (n Namespace) String() string {
- switch n.Format {
- case NamespaceFormatEd25519V1:
- return fmt.Sprintf("%x", n.NamespaceEd25519V1.Namespace)
- default:
- return "reserved"
- }
-}
-
-// NewNamespaceEd25519V1 returns an new Ed25519V1 namespace based on a
-// verification key.
-func NewNamespaceEd25519V1(vk []byte) (*Namespace, error) {
- if len(vk) != 32 {
- return nil, fmt.Errorf("invalid verification key: must be 32 bytes")
- }
- return &Namespace{
- Format: NamespaceFormatEd25519V1,
- NamespaceEd25519V1: &NamespaceEd25519V1{
- Namespace: vk,
- },
- }, nil
-}
-
-// Verify checks that signature is valid over message for this namespace
-func (ns *Namespace) Verify(message, signature []byte) error {
- switch ns.Format {
- case NamespaceFormatEd25519V1:
- if !ed25519.Verify(ed25519.PublicKey(ns.NamespaceEd25519V1.Namespace), message, signature) {
- return fmt.Errorf("ed25519 signature verification failed")
- }
- default:
- return fmt.Errorf("namespace not supported: %v", ns.Format)
- }
- return nil
-}
-
-func (ns *Namespace) Marshal() ([]byte, error) {
- serialized, err := tls.Marshal(*ns)
- if err != nil {
- return nil, fmt.Errorf("marshaled failed for namespace(%v): %v", ns.Format, err)
- }
- return serialized, err
-}
-
-func (ns *Namespace) Unmarshal(serialized []byte) error {
- extra, err := tls.Unmarshal(serialized, ns)
- if err != nil {
- return fmt.Errorf("unmarshal failed for namespace: %v", err)
- } else if len(extra) > 0 {
- return fmt.Errorf("unmarshal found extra data for namespace(%v): %v", ns.Format, err)
- }
- return nil
-}
-
-// NamespacePool is a pool of namespaces that contain complete verification keys
-type NamespacePool struct {
- pool map[string]*Namespace
- list []*Namespace
- // If we need to update this structure without a restart => add mutex.
-}
-
-// NewNameSpacePool creates a new namespace pool from a list of namespaces. An
-// error is returned if there are duplicate namespaces or namespaces without a
-// complete verification key. The latter is determined by namespaceWithKey().
-func NewNamespacePool(namespaces []*Namespace) (*NamespacePool, error) {
- np := &NamespacePool{
- pool: make(map[string]*Namespace),
- list: make([]*Namespace, 0),
- }
- for _, namespace := range namespaces {
- if !namespaceWithKey(namespace.Format) {
- return nil, fmt.Errorf("need verification key in namespace pool: %v", namespace.Format)
- }
- if _, ok := np.pool[namespace.String()]; ok {
- return nil, fmt.Errorf("duplicate namespace: %v", namespace.String())
- }
- np.pool[namespace.String()] = namespace
- np.list = append(np.list, namespace)
- }
- return np, nil
-}
-
-// Find checks if namespace is a member of the namespace pool.
-func (np *NamespacePool) Find(namespace *Namespace) (*Namespace, bool) {
- if _, ok := np.pool[namespace.String()]; !ok {
- return nil, false
- }
- // If the passed namespace is a key fingerprint the actual key needs to be
- // attached before returning. Not applicable for Ed25519. Docdoc later.
- return namespace, true
-}
-
-// List returns a copied list of namespaces that is used by this pool.
-func (np *NamespacePool) List() []*Namespace {
- namespaces := make([]*Namespace, len(np.list))
- copy(namespaces, np.list)
- return namespaces
-}
-
-// namespaceWithKey returns true if a namespace format contains a complete
-// verification key. I.e., some formats might have a key fingerprint instead.
-func namespaceWithKey(format NamespaceFormat) bool {
- switch format {
- case NamespaceFormatEd25519V1:
- return true
- default:
- return false
- }
-}
diff --git a/namespace/namespace_test.go b/namespace/namespace_test.go
deleted file mode 100644
index 10c0bf0..0000000
--- a/namespace/namespace_test.go
+++ /dev/null
@@ -1,218 +0,0 @@
-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
-}
diff --git a/namespace/testdata/data.go b/namespace/testdata/data.go
deleted file mode 100644
index 5f3f4df..0000000
--- a/namespace/testdata/data.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package testdata
-
-import (
- "encoding/base64"
-)
-
-var (
- Ed25519Vk = mustDecodeB64("HOQFUkKNWpjYAhNKTyWCzahlI7RDtf5123kHD2LACj0=")
- Ed25519Sk = mustDecodeB64("Zaajc50Xt1tNpTj6WYkljzcVjLXL2CcQcHFT/xZqYEcc5AVSQo1amNgCE0pPJYLNqGUjtEO1/nXbeQcPYsAKPQ==")
-
- Ed25519Vk2 = mustDecodeB64("LqrWb9JwQUTk/SwTNDdMH8aRmy3mbmhwEepO5WSgb+A=")
- Ed25519Sk2 = mustDecodeB64("fDkSq4cWvG72yMhUyHVcZ72QKerZ66msgyVqDvfufZQuqtZv0nBBROT9LBM0N0wfxpGbLeZuaHAR6k7lZKBv4A==")
-
- Ed25519Vk3 = mustDecodeB64("Icd1U1oY0z+5iAwgCQZyGI+pycGs6GI2rQO8gAzT7Y0=")
- Ed25519Sk3 = mustDecodeB64("Q6uNL7VKv9flaBIXBXy/NyhNOicLYKKmfuJ6tLReMvQhx3VTWhjTP7mIDCAJBnIYj6nJwazoYjatA7yADNPtjQ==")
-)
-
-func mustDecodeB64(s string) []byte {
- b, _ := base64.StdEncoding.DecodeString(s)
- return b
-}