Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configurable algorithms in verification #76

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions cmd/sigstore-go/main.go
tetsuo-cpp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package main

import (
"crypto"
"crypto/ecdsa"
"crypto/x509"
"encoding/hex"
"encoding/json"
Expand Down Expand Up @@ -154,7 +153,11 @@ func run() error {
if err != nil {
return err
}
trustedMaterial = append(trustedMaterial, trustedPublicKeyMaterial(pubKey))
hashFunc, err := verify.GetHashForDigestAlgorithm(*artifactDigestAlgorithm)
if err != nil {
return err
}
trustedMaterial = append(trustedMaterial, trustedPublicKeyMaterial(pubKey, hashFunc))
}

if len(trustedMaterial) == 0 {
Expand Down Expand Up @@ -205,9 +208,9 @@ func (*nonExpiringVerifier) ValidAtTime(_ time.Time) bool {
return true
}

func trustedPublicKeyMaterial(pk crypto.PublicKey) *root.TrustedPublicKeyMaterial {
func trustedPublicKeyMaterial(pk crypto.PublicKey, hash crypto.Hash) *root.TrustedPublicKeyMaterial {
return root.NewTrustedPublicKeyMaterial(func(string) (root.TimeConstrainedVerifier, error) {
verifier, err := signature.LoadECDSAVerifier(pk.(*ecdsa.PublicKey), crypto.SHA256)
verifier, err := signature.LoadVerifier(pk, hash)
if err != nil {
return nil, err
}
Expand Down
71 changes: 49 additions & 22 deletions pkg/verify/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"encoding/hex"
"errors"
"fmt"
"hash"
"io"

"github.com/secure-systems-lab/go-securesystemslib/dsse"
Expand Down Expand Up @@ -54,14 +53,21 @@
var verifier signature.Verifier
var err error

verifier, err = getSignatureVerifier(verificationContent, trustedMaterial)
if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}

if envelope := sigContent.EnvelopeContent(); envelope != nil {
verifier, err = getSignatureVerifier(verificationContent, trustedMaterial)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, the envelope flow just uses the defaults that we had before.

if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}
return verifyEnvelopeWithArtifact(verifier, envelope, artifact)
} else if msg := sigContent.MessageSignatureContent(); msg != nil {
hashFunc, err := GetHashForDigestAlgorithm(msg.DigestAlgorithm())
if err != nil {
return fmt.Errorf("could not find hash for message signature: %w", err)
}
verifier, err = getSignatureVerifierWithHash(verificationContent, trustedMaterial, hashFunc)
if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}
return verifyMessageSignature(verifier, msg, artifact)
} else {
// should never happen, but just in case:
Expand All @@ -73,25 +79,35 @@
var verifier signature.Verifier
var err error

verifier, err = getSignatureVerifier(verificationContent, trustedMaterial)
if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}

if envelope := sigContent.EnvelopeContent(); envelope != nil {
verifier, err = getSignatureVerifier(verificationContent, trustedMaterial)
if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}
return verifyEnvelopeWithArtifactDigest(verifier, envelope, artifactDigest, artifactDigestAlgorithm)
} else if msg := sigContent.MessageSignatureContent(); msg != nil {
hashFunc, err := GetHashForDigestAlgorithm(msg.DigestAlgorithm())
if err != nil {
return fmt.Errorf("could not find hash for message signature: %w", err)
}
verifier, err = getSignatureVerifierWithHash(verificationContent, trustedMaterial, hashFunc)
if err != nil {
return fmt.Errorf("could not load signature verifier: %w", err)
}
return verifyMessageSignatureWithArtifactDigest(verifier, msg, artifactDigest)
} else {
// should never happen, but just in case:
return fmt.Errorf("signature content has neither an envelope or a message")
}
}

func getSignatureVerifier(verificationContent VerificationContent, tm root.TrustedMaterial) (signature.Verifier, error) {
func getSignatureVerifier(content VerificationContent, tm root.TrustedMaterial) (signature.Verifier, error) {
return getSignatureVerifierWithHash(content, tm, crypto.SHA256)
}

func getSignatureVerifierWithHash(verificationContent VerificationContent, tm root.TrustedMaterial, hash crypto.Hash) (signature.Verifier, error) {
if leafCert, ok := verificationContent.HasCertificate(); ok {
// TODO: Inspect certificate's SignatureAlgorithm to determine hash function
return signature.LoadVerifier(leafCert.PublicKey, crypto.SHA256)
return signature.LoadVerifier(leafCert.PublicKey, hash)
} else if pk, ok := verificationContent.HasPublicKey(); ok {
return tm.PublicKeyVerifier(pk.Hint())
tetsuo-cpp marked this conversation as resolved.
Show resolved Hide resolved
} else {
Expand Down Expand Up @@ -155,15 +171,11 @@
}

// Compute digest of the artifact.
var hasher hash.Hash
switch artifactDigestAlgorithm {
case "sha512":
hasher = crypto.SHA512.New()
case "sha384":
hasher = crypto.SHA384.New()
case "sha256":
hasher = crypto.SHA256.New()
hashFunc, err := GetHashForDigestAlgorithm(artifactDigestAlgorithm)
if err != nil {
return fmt.Errorf("could not verify artifact: unrecognized digest algorithm: %s", err)

Check failure on line 176 in pkg/verify/signature.go

View workflow job for this annotation

GitHub Actions / lint

non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)
}
hasher := hashFunc.New()
_, err = io.Copy(hasher, artifact)
if err != nil {
return fmt.Errorf("could not verify artifact: unable to calculate digest: %w", err)
Expand Down Expand Up @@ -234,3 +246,18 @@

return nil
}

func GetHashForDigestAlgorithm(digestAlgorithm string) (crypto.Hash, error) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Figure out what this value should look like for Ed25519.

var hashFunc crypto.Hash
switch digestAlgorithm {
case "sha256":
hashFunc = crypto.SHA256
case "sha384":
hashFunc = crypto.SHA384
case "sha512":
hashFunc = crypto.SHA512
default:
return crypto.Hash(0), fmt.Errorf("unrecognized digest algorithm: %s", digestAlgorithm)
}
return hashFunc, nil
}
Loading