1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package minisign
17
18 import (
19 "bytes"
20 "crypto/ed25519"
21 "crypto/sha256"
22 "encoding/base64"
23 "encoding/hex"
24 "errors"
25 "fmt"
26 "io"
27 "strings"
28
29 minisign "github.com/jedisct1/go-minisign"
30 "github.com/sigstore/rekor/pkg/pki/identity"
31 "github.com/sigstore/sigstore/pkg/cryptoutils"
32 sigsig "github.com/sigstore/sigstore/pkg/signature"
33 "golang.org/x/crypto/blake2b"
34 )
35
36
37 type Signature struct {
38 signature *minisign.Signature
39 }
40
41
42 func NewSignature(r io.Reader) (*Signature, error) {
43 var s Signature
44 var inputBuffer bytes.Buffer
45
46 if _, err := io.Copy(&inputBuffer, r); err != nil {
47 return nil, fmt.Errorf("unable to read minisign signature: %w", err)
48 }
49
50 inputString := inputBuffer.String()
51 signature, err := minisign.DecodeSignature(inputString)
52 if err != nil {
53
54 lines := strings.Split(strings.TrimRight(inputString, "\n"), "\n")
55 if len(lines) != 2 {
56 return nil, fmt.Errorf("invalid signature provided: %v lines detected", len(lines))
57 }
58 sigBytes, b64Err := base64.StdEncoding.DecodeString(lines[1])
59 if b64Err != nil {
60 return nil, errors.New("invalid signature provided: base64 decoding failed")
61 }
62 if len(sigBytes) != len(signature.SignatureAlgorithm)+len(signature.KeyId)+len(signature.Signature) {
63 return nil, fmt.Errorf("invalid signature provided: incorrect size %v detected", len(sigBytes))
64 }
65 copy(signature.SignatureAlgorithm[:], sigBytes[0:2])
66 copy(signature.KeyId[:], sigBytes[2:10])
67 copy(signature.Signature[:], sigBytes[10:])
68 }
69
70 s.signature = &signature
71 return &s, nil
72 }
73
74
75 func (s Signature) CanonicalValue() ([]byte, error) {
76 if s.signature == nil {
77 return nil, errors.New("minisign signature has not been initialized")
78 }
79
80 buf := bytes.NewBuffer([]byte("untrusted comment:\n"))
81 b64Buf := bytes.NewBuffer(s.signature.SignatureAlgorithm[:])
82 if _, err := b64Buf.Write(s.signature.KeyId[:]); err != nil {
83 return nil, fmt.Errorf("error canonicalizing minisign signature: %w", err)
84 }
85 if _, err := b64Buf.Write(s.signature.Signature[:]); err != nil {
86 return nil, fmt.Errorf("error canonicalizing minisign signature: %w", err)
87 }
88 if _, err := buf.WriteString(base64.StdEncoding.EncodeToString(b64Buf.Bytes())); err != nil {
89 return nil, fmt.Errorf("error canonicalizing minisign signature: %w", err)
90 }
91 return buf.Bytes(), nil
92 }
93
94
95 func (s Signature) Verify(r io.Reader, k interface{}, opts ...sigsig.VerifyOption) error {
96 if s.signature == nil {
97 return errors.New("minisign signature has not been initialized")
98 }
99
100 key, ok := k.(*PublicKey)
101 if !ok {
102 return errors.New("cannot use Verify with a non-minisign key")
103 }
104 if key.key == nil {
105 return errors.New("minisign public key has not been initialized")
106 }
107
108 verifier, err := sigsig.LoadED25519Verifier(key.key.PublicKey[:])
109 if err != nil {
110 return err
111 }
112
113 prehashed := s.signature.SignatureAlgorithm[1] == 0x44
114 if prehashed {
115 h, _ := blake2b.New512(nil)
116 _, err := io.Copy(h, r)
117 if err != nil {
118 return errors.New("reading minisign data")
119 }
120 r = bytes.NewReader(h.Sum(nil))
121 }
122
123 return verifier.VerifySignature(bytes.NewReader(s.signature.Signature[:]), r, opts...)
124 }
125
126
127 type PublicKey struct {
128 key *minisign.PublicKey
129 }
130
131
132 func NewPublicKey(r io.Reader) (*PublicKey, error) {
133 var k PublicKey
134 var inputBuffer bytes.Buffer
135
136 if _, err := io.Copy(&inputBuffer, r); err != nil {
137 return nil, fmt.Errorf("unable to read minisign public key: %w", err)
138 }
139
140 inputString := inputBuffer.String()
141
142
143
144
145
146 key, err := minisign.DecodePublicKey(inputString)
147 if err == nil {
148 k.key = &key
149 return &k, nil
150 }
151 key, err = minisign.NewPublicKey(inputString)
152 if err == nil {
153 k.key = &key
154 return &k, nil
155 }
156
157 if len(inputString) == 32 {
158 k.key = &minisign.PublicKey{
159 SignatureAlgorithm: [2]byte{'E', 'd'},
160 KeyId: [8]byte{},
161 }
162 copy(k.key.PublicKey[:], inputBuffer.Bytes())
163 return &k, nil
164 }
165 return nil, fmt.Errorf("unable to read minisign public key: %w", err)
166 }
167
168
169 func (k PublicKey) CanonicalValue() ([]byte, error) {
170 if k.key == nil {
171 return nil, errors.New("minisign public key has not been initialized")
172 }
173
174 bin := []byte{}
175 bin = append(bin, k.key.SignatureAlgorithm[:]...)
176 bin = append(bin, k.key.KeyId[:]...)
177 bin = append(bin, k.key.PublicKey[:]...)
178 b64Key := base64.StdEncoding.EncodeToString(bin)
179 return []byte(b64Key), nil
180 }
181
182
183 func (k PublicKey) EmailAddresses() []string {
184 return nil
185 }
186
187
188 func (k PublicKey) Subjects() []string {
189 return nil
190 }
191
192
193 func (k PublicKey) Identities() ([]identity.Identity, error) {
194
195 pkixKey, err := cryptoutils.MarshalPublicKeyToDER(ed25519.PublicKey(k.key.PublicKey[:]))
196 if err != nil {
197 return nil, err
198 }
199 digest := sha256.Sum256(pkixKey)
200 return []identity.Identity{{
201 Crypto: k.key,
202 Raw: pkixKey,
203 Fingerprint: hex.EncodeToString(digest[:]),
204 }}, nil
205 }
206
View as plain text