@@ -41,10 +41,10 @@ import (
4141
4242 "github.com/sigstore/cosign/pkg/cosign"
4343 "github.com/sigstore/cosign/pkg/cosign/fulcio"
44+ "github.com/sigstore/cosign/pkg/cosign/pivkey"
4445 cremote "github.com/sigstore/cosign/pkg/cosign/remote"
4546 "github.com/sigstore/rekor/pkg/generated/models"
4647
47- "github.com/sigstore/cosign/pkg/cosign/pivkey"
4848 rekorClient "github.com/sigstore/rekor/pkg/client"
4949 "github.com/sigstore/sigstore/pkg/signature"
5050 "github.com/sigstore/sigstore/pkg/signature/options"
@@ -223,86 +223,9 @@ func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{}
223223 }
224224 toSign = append (toSign , imgs ... )
225225 }
226-
227- var signerVerifier signature.SignerVerifier
228- var cert , chain string
229- switch {
230- case ko .Sk :
231- sk , err := pivkey .GetKeyWithSlot (ko .Slot )
232- defer sk .Close ()
233- if err != nil {
234- return err
235- }
236- sv , err := sk .SignerVerifier ()
237- if err != nil {
238- return err
239- }
240- signerVerifier = sv
241-
242- // Handle the -cert flag.
243- // With PIV, we assume the certificate is in the same slot on the PIV
244- // token as the private key. If it's not there, show a warning to the
245- // user.
246- certFromPIV , err := sk .Certificate ()
247- if err != nil {
248- fmt .Fprintln (os .Stderr , "warning: no x509 certificate retrieved from the PIV token" )
249- break
250- }
251- cert = string (cosign .CertToPem (certFromPIV ))
252-
253- case ko .KeyRef != "" :
254- k , err := signerVerifierFromKeyRef (ctx , ko .KeyRef , ko .PassFunc )
255- if err != nil {
256- return errors .Wrap (err , "reading key" )
257- }
258- signerVerifier = k
259-
260- // Handle the -cert flag
261- if certPath == "" {
262- break
263- }
264- certBytes , err := ioutil .ReadFile (certPath )
265- if err != nil {
266- return errors .Wrap (err , "read certificate" )
267- }
268- // Handle PEM.
269- if bytes .HasPrefix (certBytes , []byte ("-----" )) {
270- decoded , _ := pem .Decode (certBytes )
271- if decoded .Type != "CERTIFICATE" {
272- return fmt .Errorf ("supplied PEM file is not a certificate: %s" , certPath )
273- }
274- certBytes = decoded .Bytes
275- }
276- parsedCert , err := x509 .ParseCertificate (certBytes )
277- if err != nil {
278- return errors .Wrap (err , "parse x509 certificate" )
279- }
280- pk , err := k .PublicKey ()
281- if err != nil {
282- return errors .Wrap (err , "get public key" )
283- }
284- switch kt := parsedCert .PublicKey .(type ) {
285- case * ecdsa.PublicKey :
286- if ! kt .Equal (pk ) {
287- return errors .New ("public key in certificate does not match that in the signing key" )
288- }
289- case * rsa.PublicKey :
290- if ! kt .Equal (pk ) {
291- return errors .New ("public key in certificate does not match that in the signing key" )
292- }
293- default :
294- return fmt .Errorf ("unsupported key type: %T" , parsedCert .PublicKey )
295- }
296- cert = string (cosign .CertToPem (parsedCert ))
297-
298- default : // Keyless!
299- fmt .Fprintln (os .Stderr , "Generating ephemeral keys..." )
300- k , err := fulcio .NewSigner (ctx , ko .IDToken )
301- if err != nil {
302- return errors .Wrap (err , "getting key from Fulcio" )
303- }
304- signerVerifier = k
305- cert , chain = k .Cert , k .Chain
226+ sv , err := signerFromKeyOpts (ctx , certPath , ko )
227+ if err != nil {
228+ return errors .Wrap (err , "getting signer" )
306229 }
307230
308231 // Check if the image is public (no auth in Get)
@@ -325,10 +248,10 @@ func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{}
325248 var rekorBytes []byte
326249 if uploadTLog {
327250 // Upload the cert or the public key, depending on what we have
328- if cert != "" {
329- rekorBytes = []byte (cert )
251+ if sv . Cert != "" {
252+ rekorBytes = []byte (sv . Cert )
330253 } else {
331- pemBytes , err := cosign .PublicKeyPem (signerVerifier , options .WithContext (ctx ))
254+ pemBytes , err := cosign .PublicKeyPem (sv , options .WithContext (ctx ))
332255 if err != nil {
333256 return err
334257 }
@@ -360,7 +283,7 @@ func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{}
360283 }
361284 }
362285
363- sig , err := signerVerifier .SignMessage (bytes .NewReader (payload ), options .WithContext (ctx ))
286+ sig , err := sv .SignMessage (bytes .NewReader (payload ), options .WithContext (ctx ))
364287 if err != nil {
365288 return errors .Wrap (err , "signing" )
366289 }
@@ -385,9 +308,9 @@ func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{}
385308 }, cosign .SuffixSignature )
386309
387310 uo := cremote.UploadOpts {
388- Cert : cert ,
389- Chain : chain ,
390- DupeDetector : signerVerifier ,
311+ Cert : sv . Cert ,
312+ Chain : sv . Chain ,
313+ DupeDetector : sv ,
391314 RemoteOpts : remoteOpts ,
392315 }
393316
@@ -438,3 +361,99 @@ func parseAnnotations(entry *models.LogEntryAnon) map[string]string {
438361 }
439362 return annts
440363}
364+
365+ func signerFromKeyOpts (ctx context.Context , certPath string , ko KeyOpts ) (* certSignVerifier , error ) {
366+ switch {
367+ case ko .Sk :
368+ sk , err := pivkey .GetKeyWithSlot (ko .Slot )
369+ defer sk .Close ()
370+ if err != nil {
371+ return nil , err
372+ }
373+ sv , err := sk .SignerVerifier ()
374+ if err != nil {
375+ return nil , err
376+ }
377+
378+ // Handle the -cert flag.
379+ // With PIV, we assume the certificate is in the same slot on the PIV
380+ // token as the private key. If it's not there, show a warning to the
381+ // user.
382+ certFromPIV , err := sk .Certificate ()
383+ if err != nil {
384+ fmt .Fprintln (os .Stderr , "warning: no x509 certificate retrieved from the PIV token" )
385+ break
386+ }
387+ cert := string (cosign .CertToPem (certFromPIV ))
388+ return & certSignVerifier {
389+ Cert : cert ,
390+ SignerVerifier : sv ,
391+ }, nil
392+
393+ case ko .KeyRef != "" :
394+ k , err := signerVerifierFromKeyRef (ctx , ko .KeyRef , ko .PassFunc )
395+ if err != nil {
396+ return nil , errors .Wrap (err , "reading key" )
397+ }
398+
399+ certSigner := & certSignVerifier {
400+ SignerVerifier : k ,
401+ }
402+ // Handle the -cert flag
403+ if certPath == "" {
404+ return certSigner , nil
405+ }
406+
407+ certBytes , err := ioutil .ReadFile (certPath )
408+ if err != nil {
409+ return nil , errors .Wrap (err , "read certificate" )
410+ }
411+ // Handle PEM.
412+ if bytes .HasPrefix (certBytes , []byte ("-----" )) {
413+ decoded , _ := pem .Decode (certBytes )
414+ if decoded .Type != "CERTIFICATE" {
415+ return nil , fmt .Errorf ("supplied PEM file is not a certificate: %s" , certPath )
416+ }
417+ certBytes = decoded .Bytes
418+ }
419+ parsedCert , err := x509 .ParseCertificate (certBytes )
420+ if err != nil {
421+ return nil , errors .Wrap (err , "parse x509 certificate" )
422+ }
423+ pk , err := k .PublicKey ()
424+ if err != nil {
425+ return nil , errors .Wrap (err , "get public key" )
426+ }
427+ switch kt := parsedCert .PublicKey .(type ) {
428+ case * ecdsa.PublicKey :
429+ if ! kt .Equal (pk ) {
430+ return nil , errors .New ("public key in certificate does not match that in the signing key" )
431+ }
432+ case * rsa.PublicKey :
433+ if ! kt .Equal (pk ) {
434+ return nil , errors .New ("public key in certificate does not match that in the signing key" )
435+ }
436+ default :
437+ return nil , fmt .Errorf ("unsupported key type: %T" , parsedCert .PublicKey )
438+ }
439+ certSigner .Cert = string (cosign .CertToPem (parsedCert ))
440+ return certSigner , nil
441+ }
442+ // Default Keyless!
443+ fmt .Fprintln (os .Stderr , "Generating ephemeral keys..." )
444+ k , err := fulcio .NewSigner (ctx , ko .IDToken )
445+ if err != nil {
446+ return nil , errors .Wrap (err , "getting key from Fulcio" )
447+ }
448+ return & certSignVerifier {
449+ Cert : k .Cert ,
450+ Chain : k .Chain ,
451+ SignerVerifier : k ,
452+ }, nil
453+ }
454+
455+ type certSignVerifier struct {
456+ Cert string
457+ Chain string
458+ signature.SignerVerifier
459+ }
0 commit comments