aboutsummaryrefslogtreecommitdiff
path: root/types/namespace.go
blob: 3c6b90a074c59ed937f13532c38391e43db32b3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package types

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

	NamespaceFingerprintSize = 32
)

// Namespace references a versioned namespace based on a given format specifier
type Namespace struct {
	Format    NamespaceFormat `tls:"maxval:65535"`
	Ed25519V1 *Ed25519V1      `tls:"selector:Format,val:1"`
}

// Ed25519V1 uses an Ed25519 verification key as namespace.  Encoding,
// signing, and verification operations are defined by RFC 8032.
type Ed25519V1 struct {
	Namespace [32]byte
}

func (f NamespaceFormat) String() string {
	switch f {
	case NamespaceFormatReserved:
		return "reserved"
	case NamespaceFormatEd25519V1:
		return "ed25519_v1"
	default:
		return fmt.Sprintf("unknown NamespaceFormat: %d", f)
	}
}

func (n Namespace) String() string {
	switch n.Format {
	case NamespaceFormatReserved:
		return fmt.Sprintf("Format(%s)", n.Format)
	case NamespaceFormatEd25519V1:
		return fmt.Sprintf("Format(%s): %+v", n.Format, n.Ed25519V1)
	default:
		return fmt.Sprintf("unknown Namespace: %v", n.Format)
	}
}

// Fingerprint returns a fixed-size namespace fingerprint that is unique.
func (n *Namespace) Fingerprint() (*[NamespaceFingerprintSize]byte, error) {
	switch n.Format {
	case NamespaceFormatEd25519V1:
		return &n.Ed25519V1.Namespace, nil
	default:
		return nil, fmt.Errorf("unsupported NamespaceFormat: %v", n.Format)
	}
}

// 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")
	}

	var ed25519v1 Ed25519V1
	copy(ed25519v1.Namespace[:], vk)
	return &Namespace{
		Format:    NamespaceFormatEd25519V1,
		Ed25519V1: &ed25519v1,
	}, 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.Ed25519V1.Namespace[:]), message, signature) {
			return fmt.Errorf("ed25519 signature verification failed")
		}
	default:
		return fmt.Errorf("namespace not supported: %v", ns.Format)
	}
	return nil
}