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
}
|