2016-11-22 19:32:10 +00:00
|
|
|
// Note: Consider the API unstable until the code supports at least three different image formats or transports.
|
|
|
|
|
|
|
|
package signature
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2017-02-01 00:45:59 +00:00
|
|
|
"github.com/containers/image/docker/reference"
|
2016-11-22 19:32:10 +00:00
|
|
|
"github.com/containers/image/manifest"
|
2016-10-17 13:53:40 +00:00
|
|
|
"github.com/opencontainers/go-digest"
|
2016-11-22 19:32:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// SignDockerManifest returns a signature for manifest as the specified dockerReference,
|
|
|
|
// using mech and keyIdentity.
|
|
|
|
func SignDockerManifest(m []byte, dockerReference string, mech SigningMechanism, keyIdentity string) ([]byte, error) {
|
|
|
|
manifestDigest, err := manifest.Digest(m)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-02-01 00:45:59 +00:00
|
|
|
sig := newUntrustedSignature(manifestDigest, dockerReference)
|
2016-11-22 19:32:10 +00:00
|
|
|
return sig.sign(mech, keyIdentity)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyDockerManifestSignature checks that unverifiedSignature uses expectedKeyIdentity to sign unverifiedManifest as expectedDockerReference,
|
|
|
|
// using mech.
|
|
|
|
func VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest []byte,
|
|
|
|
expectedDockerReference string, mech SigningMechanism, expectedKeyIdentity string) (*Signature, error) {
|
2017-03-13 16:33:17 +00:00
|
|
|
expectedRef, err := reference.ParseNormalizedNamed(expectedDockerReference)
|
2017-02-01 00:45:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-11-22 19:32:10 +00:00
|
|
|
sig, err := verifyAndExtractSignature(mech, unverifiedSignature, signatureAcceptanceRules{
|
|
|
|
validateKeyIdentity: func(keyIdentity string) error {
|
|
|
|
if keyIdentity != expectedKeyIdentity {
|
|
|
|
return InvalidSignatureError{msg: fmt.Sprintf("Signature by %s does not match expected fingerprint %s", keyIdentity, expectedKeyIdentity)}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
validateSignedDockerReference: func(signedDockerReference string) error {
|
2017-03-13 16:33:17 +00:00
|
|
|
signedRef, err := reference.ParseNormalizedNamed(signedDockerReference)
|
2017-02-01 00:45:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return InvalidSignatureError{msg: fmt.Sprintf("Invalid docker reference %s in signature", signedDockerReference)}
|
|
|
|
}
|
|
|
|
if signedRef.String() != expectedRef.String() {
|
2016-11-22 19:32:10 +00:00
|
|
|
return InvalidSignatureError{msg: fmt.Sprintf("Docker reference %s does not match %s",
|
|
|
|
signedDockerReference, expectedDockerReference)}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
validateSignedDockerManifestDigest: func(signedDockerManifestDigest digest.Digest) error {
|
|
|
|
matches, err := manifest.MatchesDigest(unverifiedManifest, signedDockerManifestDigest)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !matches {
|
|
|
|
return InvalidSignatureError{msg: fmt.Sprintf("Signature for docker digest %q does not match", signedDockerManifestDigest)}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return sig, nil
|
|
|
|
}
|