1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package x509
17
18 import (
19 "bytes"
20 "crypto"
21 "crypto/sha256"
22 "crypto/x509"
23 "encoding/asn1"
24 "encoding/hex"
25 "encoding/pem"
26 "errors"
27 "fmt"
28 "io"
29 "strings"
30
31 "github.com/asaskevich/govalidator"
32 "github.com/sigstore/rekor/pkg/pki/identity"
33 "github.com/sigstore/sigstore/pkg/cryptoutils"
34 sigsig "github.com/sigstore/sigstore/pkg/signature"
35 )
36
37
38 var EmailAddressOID asn1.ObjectIdentifier = []int{1, 2, 840, 113549, 1, 9, 1}
39
40 type Signature struct {
41 signature []byte
42 verifierLoadOpts []sigsig.LoadOption
43 }
44
45
46 func NewSignature(r io.Reader) (*Signature, error) {
47 return NewSignatureWithOpts(r)
48 }
49
50 func NewSignatureWithOpts(r io.Reader, opts ...sigsig.LoadOption) (*Signature, error) {
51 b, err := io.ReadAll(r)
52 if err != nil {
53 return nil, err
54 }
55 return &Signature{
56 signature: b,
57 verifierLoadOpts: opts,
58 }, nil
59 }
60
61
62 func (s Signature) CanonicalValue() ([]byte, error) {
63 return s.signature, nil
64 }
65
66
67 func (s Signature) Verify(r io.Reader, k interface{}, opts ...sigsig.VerifyOption) error {
68 if len(s.signature) == 0 {
69
70 return errors.New("X509 signature has not been initialized")
71 }
72
73 key, ok := k.(*PublicKey)
74 if !ok {
75 return fmt.Errorf("invalid public key type for: %v", k)
76 }
77
78 p := key.key
79 if p == nil {
80 switch {
81 case key.cert != nil:
82 p = key.cert.c.PublicKey
83 case len(key.certs) > 0:
84 if err := verifyCertChain(key.certs); err != nil {
85 return err
86 }
87 p = key.certs[0].PublicKey
88 default:
89 return errors.New("no public key found")
90 }
91 }
92
93 verifier, err := sigsig.LoadVerifierWithOpts(p, s.verifierLoadOpts...)
94 if err != nil {
95 return err
96 }
97 return verifier.VerifySignature(bytes.NewReader(s.signature), r, opts...)
98 }
99
100
101 type PublicKey struct {
102 key interface{}
103 cert *cert
104 certs []*x509.Certificate
105 }
106
107 type cert struct {
108 c *x509.Certificate
109 b []byte
110 }
111
112
113 func NewPublicKey(r io.Reader) (*PublicKey, error) {
114 rawPub, err := io.ReadAll(r)
115 if err != nil {
116 return nil, err
117 }
118 trimmedRawPub := bytes.TrimSpace(rawPub)
119
120 block, rest := pem.Decode(trimmedRawPub)
121 if block == nil {
122 return nil, errors.New("invalid public key: failure decoding PEM")
123 }
124
125
126 if len(rest) > 0 {
127
128 certs, err := cryptoutils.UnmarshalCertificatesFromPEMLimited(trimmedRawPub, 10)
129 if err != nil {
130 return nil, err
131 }
132 return &PublicKey{certs: certs}, nil
133 }
134
135 switch block.Type {
136 case string(cryptoutils.PublicKeyPEMType):
137 key, err := x509.ParsePKIXPublicKey(block.Bytes)
138 if err != nil {
139 return nil, err
140 }
141 return &PublicKey{key: key}, nil
142 case string(cryptoutils.CertificatePEMType):
143 c, err := x509.ParseCertificate(block.Bytes)
144 if err != nil {
145 return nil, err
146 }
147 return &PublicKey{
148 cert: &cert{
149 c: c,
150 b: block.Bytes,
151 }}, nil
152 }
153 return nil, fmt.Errorf("invalid public key: cannot handle type %v", block.Type)
154 }
155
156
157 func (k PublicKey) CanonicalValue() (encoded []byte, err error) {
158
159 switch {
160 case k.key != nil:
161 encoded, err = cryptoutils.MarshalPublicKeyToPEM(k.key)
162 case k.cert != nil:
163 encoded, err = cryptoutils.MarshalCertificateToPEM(k.cert.c)
164 case k.certs != nil:
165 encoded, err = cryptoutils.MarshalCertificatesToPEM(k.certs)
166 default:
167 err = errors.New("x509 public key has not been initialized")
168 }
169
170 return
171 }
172
173 func (k PublicKey) CryptoPubKey() crypto.PublicKey {
174 if k.cert != nil {
175 return k.cert.c.PublicKey
176 }
177 if len(k.certs) > 0 {
178 return k.certs[0].PublicKey
179 }
180 return k.key
181 }
182
183
184 func (k PublicKey) EmailAddresses() []string {
185 var names []string
186 var cert *x509.Certificate
187 if k.cert != nil {
188 cert = k.cert.c
189 } else if len(k.certs) > 0 {
190 cert = k.certs[0]
191 }
192 if cert != nil {
193 for _, name := range cert.EmailAddresses {
194 if govalidator.IsEmail(name) {
195 names = append(names, strings.ToLower(name))
196 }
197 }
198 }
199 return names
200 }
201
202
203 func (k PublicKey) Subjects() []string {
204 var subjects []string
205 var cert *x509.Certificate
206 if k.cert != nil {
207 cert = k.cert.c
208 } else if len(k.certs) > 0 {
209 cert = k.certs[0]
210 }
211 if cert != nil {
212 subjects = cryptoutils.GetSubjectAlternateNames(cert)
213 }
214 return subjects
215 }
216
217
218 func (k PublicKey) Identities() ([]identity.Identity, error) {
219
220 if k.key != nil {
221 pkixKey, err := cryptoutils.MarshalPublicKeyToDER(k.key)
222 if err != nil {
223 return nil, err
224 }
225 digest := sha256.Sum256(pkixKey)
226 return []identity.Identity{{
227 Crypto: k.key,
228 Raw: pkixKey,
229 Fingerprint: hex.EncodeToString(digest[:]),
230 }}, nil
231 }
232
233 var cert *x509.Certificate
234 switch {
235 case k.cert != nil:
236 cert = k.cert.c
237 case len(k.certs) > 0:
238 cert = k.certs[0]
239 default:
240 return nil, errors.New("no key, certificate or certificate chain provided")
241 }
242
243 digest := sha256.Sum256(cert.Raw)
244 return []identity.Identity{{
245 Crypto: cert,
246 Raw: cert.Raw,
247 Fingerprint: hex.EncodeToString(digest[:]),
248 }}, nil
249 }
250
251 func verifyCertChain(certChain []*x509.Certificate) error {
252 if len(certChain) == 0 {
253 return errors.New("no certificate chain provided")
254 }
255
256 if len(certChain) == 1 {
257 return nil
258 }
259 rootPool := x509.NewCertPool()
260 rootPool.AddCert(certChain[len(certChain)-1])
261 subPool := x509.NewCertPool()
262 for _, c := range certChain[1 : len(certChain)-1] {
263 subPool.AddCert(c)
264 }
265 if _, err := certChain[0].Verify(x509.VerifyOptions{
266 Roots: rootPool,
267 Intermediates: subPool,
268
269 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
270
271 CurrentTime: certChain[0].NotBefore,
272 }); err != nil {
273 return err
274 }
275 return nil
276 }
277
View as plain text