1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package signature
16
17 import (
18 "context"
19 "crypto"
20 "errors"
21 "fmt"
22 "strings"
23
24 "github.com/sigstore/cosign/v2/pkg/blob"
25 "github.com/sigstore/cosign/v2/pkg/cosign"
26 "github.com/sigstore/cosign/v2/pkg/cosign/git"
27 "github.com/sigstore/cosign/v2/pkg/cosign/git/gitlab"
28 "github.com/sigstore/cosign/v2/pkg/cosign/kubernetes"
29 "github.com/sigstore/cosign/v2/pkg/cosign/pkcs11key"
30 "github.com/sigstore/sigstore/pkg/cryptoutils"
31 "github.com/sigstore/sigstore/pkg/signature"
32
33 "github.com/sigstore/sigstore/pkg/signature/kms"
34 )
35
36
37 func LoadPublicKey(ctx context.Context, keyRef string) (verifier signature.Verifier, err error) {
38 return VerifierForKeyRef(ctx, keyRef, crypto.SHA256)
39 }
40
41
42
43 func VerifierForKeyRef(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash) (verifier signature.Verifier, err error) {
44
45 var perr *kms.ProviderNotFoundError
46 kmsKey, err := kms.Get(ctx, keyRef, hashAlgorithm)
47 switch {
48 case err == nil:
49
50 return kmsKey, nil
51 case errors.As(err, &perr):
52
53
54 default:
55
56
57 return nil, err
58 }
59
60 raw, err := blob.LoadFileOrURL(keyRef)
61
62 if err != nil {
63 return nil, err
64 }
65
66
67 pubKey, err := cryptoutils.UnmarshalPEMToPublicKey(raw)
68 if err != nil {
69 return nil, fmt.Errorf("pem to public key: %w", err)
70 }
71
72 return signature.LoadVerifier(pubKey, hashAlgorithm)
73 }
74
75 func loadKey(keyPath string, pf cosign.PassFunc) (signature.SignerVerifier, error) {
76 kb, err := blob.LoadFileOrURL(keyPath)
77 if err != nil {
78 return nil, err
79 }
80 pass := []byte{}
81 if pf != nil {
82 pass, err = pf(false)
83 if err != nil {
84 return nil, err
85 }
86 }
87 return cosign.LoadPrivateKey(kb, pass)
88 }
89
90
91 func LoadPublicKeyRaw(raw []byte, hashAlgorithm crypto.Hash) (signature.Verifier, error) {
92 pub, err := cryptoutils.UnmarshalPEMToPublicKey(raw)
93 if err != nil {
94 return nil, err
95 }
96 return signature.LoadVerifier(pub, hashAlgorithm)
97 }
98
99 func SignerFromKeyRef(ctx context.Context, keyRef string, pf cosign.PassFunc) (signature.Signer, error) {
100 return SignerVerifierFromKeyRef(ctx, keyRef, pf)
101 }
102
103 func SignerVerifierFromKeyRef(ctx context.Context, keyRef string, pf cosign.PassFunc) (signature.SignerVerifier, error) {
104 switch {
105 case strings.HasPrefix(keyRef, pkcs11key.ReferenceScheme):
106 pkcs11UriConfig := pkcs11key.NewPkcs11UriConfig()
107 err := pkcs11UriConfig.Parse(keyRef)
108 if err != nil {
109 return nil, fmt.Errorf("parsing pkcs11 uri: %w", err)
110 }
111
112
113
114 sk, err := pkcs11key.GetKeyWithURIConfig(pkcs11UriConfig, true)
115 if err != nil {
116 return nil, fmt.Errorf("opening pkcs11 token key: %w", err)
117 }
118
119 sv, err := sk.SignerVerifier()
120 if err != nil {
121 return nil, fmt.Errorf("initializing pkcs11 token signer verifier: %w", err)
122 }
123
124 return sv, nil
125 case strings.HasPrefix(keyRef, kubernetes.KeyReference):
126 s, err := kubernetes.GetKeyPairSecret(ctx, keyRef)
127 if err != nil {
128 return nil, err
129 }
130
131 if len(s.Data) > 0 {
132 return cosign.LoadPrivateKey(s.Data["cosign.key"], s.Data["cosign.password"])
133 }
134 case strings.HasPrefix(keyRef, gitlab.ReferenceScheme):
135 split := strings.Split(keyRef, "://")
136
137 if len(split) < 2 {
138 return nil, errors.New("could not parse scheme, use <scheme>://<ref> format")
139 }
140
141 provider, targetRef := split[0], split[1]
142
143 pk, err := git.GetProvider(provider).GetSecret(ctx, targetRef, "COSIGN_PRIVATE_KEY")
144 if err != nil {
145 return nil, err
146 }
147
148 pass, err := git.GetProvider(provider).GetSecret(ctx, targetRef, "COSIGN_PASSWORD")
149 if err != nil {
150 return nil, err
151 }
152
153 return cosign.LoadPrivateKey([]byte(pk), []byte(pass))
154 }
155
156 if strings.Contains(keyRef, "://") {
157 sv, err := kms.Get(ctx, keyRef, crypto.SHA256)
158 if err == nil {
159 return sv, nil
160 }
161 var e *kms.ProviderNotFoundError
162 if !errors.As(err, &e) {
163 return nil, fmt.Errorf("kms get: %w", err)
164 }
165
166 }
167
168 return loadKey(keyRef, pf)
169 }
170
171 func PublicKeyFromKeyRef(ctx context.Context, keyRef string) (signature.Verifier, error) {
172 return PublicKeyFromKeyRefWithHashAlgo(ctx, keyRef, crypto.SHA256)
173 }
174
175 func PublicKeyFromKeyRefWithHashAlgo(ctx context.Context, keyRef string, hashAlgorithm crypto.Hash) (signature.Verifier, error) {
176 if strings.HasPrefix(keyRef, kubernetes.KeyReference) {
177 s, err := kubernetes.GetKeyPairSecret(ctx, keyRef)
178 if err != nil {
179 return nil, err
180 }
181
182 if len(s.Data) > 0 {
183 return LoadPublicKeyRaw(s.Data["cosign.pub"], hashAlgorithm)
184 }
185 }
186
187 if strings.HasPrefix(keyRef, pkcs11key.ReferenceScheme) {
188 pkcs11UriConfig := pkcs11key.NewPkcs11UriConfig()
189 err := pkcs11UriConfig.Parse(keyRef)
190 if err != nil {
191 return nil, fmt.Errorf("parsing pkcs11 uri): %w", err)
192 }
193
194
195
196 sk, err := pkcs11key.GetKeyWithURIConfig(pkcs11UriConfig, false)
197 if err != nil {
198 return nil, fmt.Errorf("opening pkcs11 token key: %w", err)
199 }
200
201 v, err := sk.Verifier()
202 if err != nil {
203 return nil, fmt.Errorf("initializing pkcs11 token verifier: %w", err)
204 }
205
206 return v, nil
207 } else if strings.HasPrefix(keyRef, gitlab.ReferenceScheme) {
208 split := strings.Split(keyRef, "://")
209
210 if len(split) < 2 {
211 return nil, errors.New("could not parse scheme, use <scheme>://<ref> format")
212 }
213
214 provider, targetRef := split[0], split[1]
215
216 pubKey, err := git.GetProvider(provider).GetSecret(ctx, targetRef, "COSIGN_PUBLIC_KEY")
217 if err != nil {
218 return nil, err
219 }
220
221 if len(pubKey) > 0 {
222 return LoadPublicKeyRaw([]byte(pubKey), hashAlgorithm)
223 }
224 }
225
226 return VerifierForKeyRef(ctx, keyRef, hashAlgorithm)
227 }
228
229 func PublicKeyPem(key signature.PublicKeyProvider, pkOpts ...signature.PublicKeyOption) ([]byte, error) {
230 pub, err := key.PublicKey(pkOpts...)
231 if err != nil {
232 return nil, err
233 }
234 return cryptoutils.MarshalPublicKeyToPEM(pub)
235 }
236
View as plain text