notation package - github.com/notaryproject/notation-go - Go Packages

Package notation provides signer and verifier for notation Sign and Verification.

ExampleLocalSign demonstrates how to use signer.Sign to sign an artifact at local (without using a registry.Repository).

package main

import (
	"context"
	"crypto/x509"
	"fmt"

	"github.com/notaryproject/notation-core-go/signature"
	"github.com/notaryproject/notation-core-go/signature/cose"
	"github.com/notaryproject/notation-core-go/testhelper"
	"github.com/notaryproject/notation-go"
	"github.com/notaryproject/notation-go/signer"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

var (
	// exampleDesc is an example of the target manifest descriptor.
	exampleDesc = ocispec.Descriptor{
		MediaType: "application/vnd.docker.distribution.manifest.v2+json",
		Digest:    "sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c",
		Size:      528,
	}

	// exampleCertTuple contains a RSA privateKey and a self-signed X509
	// certificate generated for demo purpose ONLY.
	exampleCertTuple = testhelper.GetRSASelfSignedSigningCertTuple("Notation Example self-signed")
	exampleCerts     = []*x509.Certificate{exampleCertTuple.Cert}
)

// ExampleLocalSign demonstrates how to use signer.Sign to sign an artifact
// at local (without using a registry.Repository).
func main() {
	// exampleSigner is a notation.Signer given key and X509 certificate chain.
	// Users should replace `exampleCertTuple.PrivateKey` with their own private
	// key and replace `exampleCerts` with the corresponding full certificate
	// chain, following the Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleSigner, err := signer.NewGenericSigner(exampleCertTuple.PrivateKey, exampleCerts)
	if err != nil {
		panic(err) // Handle error
	}

	// Both COSE ("application/cose") and JWS ("application/jose+json")
	// signature mediaTypes are supported.
	exampleSignatureMediaType := cose.MediaTypeEnvelope

	// exampleSignOptions is an example of notation.SignerSignOptions.
	exampleSignOptions := notation.SignerSignOptions{
		SignatureMediaType: exampleSignatureMediaType,
		SigningAgent:       "example signing agent",
	}

	// local sign core process
	// upon successful signing, signature envelope and signerInfo are returned.
	// signatureEnvelope can be used in a verification process later on.
	signatureEnvelope, signerInfo, err := exampleSigner.Sign(context.Background(), exampleDesc, exampleSignOptions)
	if err != nil {
		panic(err) // Handle error
	}

	fmt.Println("Successfully signed")

	// a peek of the signature envelope generated from Sign
	sigBlob, err := signature.ParseEnvelope(exampleSignatureMediaType, signatureEnvelope)
	if err != nil {
		panic(err) // Handle error
	}
	sigContent, err := sigBlob.Content()
	if err != nil {
		panic(err) // Handle error
	}
	fmt.Println("signature Payload ContentType:", sigContent.Payload.ContentType)
	fmt.Println("signature Payload Content:", string(sigContent.Payload.Content))
	fmt.Println("signerInfo SigningAgent:", signerInfo.UnsignedAttributes.SigningAgent)

}
Output:
Successfully signed
signature Payload ContentType: application/vnd.cncf.notary.payload.v1+json
signature Payload Content: {"targetArtifact":{"mediaType":"application/vnd.docker.distribution.manifest.v2+json","digest":"sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c","size":528}}
signerInfo SigningAgent: example signing agent

ExampleLocalVerify demonstrates how to use verifier.Verify to verify a signature of the target artifact at local (without using a registry.Repository).

package main

import (
	"context"
	"encoding/pem"
	"errors"
	"fmt"
	"os"

	"github.com/notaryproject/notation-core-go/signature/cose"
	"github.com/notaryproject/notation-go"
	"github.com/notaryproject/notation-go/dir"
	"github.com/notaryproject/notation-go/verifier"
	"github.com/notaryproject/notation-go/verifier/trustpolicy"
	"github.com/notaryproject/notation-go/verifier/truststore"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// examplePolicyDocument is an example of a valid trust policy document.
// trust policy document should follow this spec:
// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy
var examplePolicyDocument = trustpolicy.Document{
	Version: "1.0",
	TrustPolicies: []trustpolicy.TrustPolicy{
		{
			Name:                  "test-statement-name",
			RegistryScopes:        []string{"example/software"},
			SignatureVerification: trustpolicy.SignatureVerification{VerificationLevel: trustpolicy.LevelStrict.Name, Override: map[trustpolicy.ValidationType]trustpolicy.ValidationAction{trustpolicy.TypeRevocation: trustpolicy.ActionSkip}},
			TrustStores:           []string{"ca:valid-trust-store"},
			TrustedIdentities:     []string{"*"},
		},
	},
}

// ExampleLocalVerify demonstrates how to use verifier.Verify to verify a
// signature of the target artifact at local (without using a
// registry.Repository).
func main() {
	// exampleArtifactReference is an example of the target artifact reference
	exampleArtifactReference := "example/software@sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c"

	// Both COSE ("application/cose") and JWS ("application/jose+json")
	// signature mediaTypes are supported.
	exampleSignatureMediaType := cose.MediaTypeEnvelope

	// exampleTargetDescriptor is an example of the target manifest descriptor.
	exampleTargetDescriptor := ocispec.Descriptor{
		MediaType: "application/vnd.docker.distribution.manifest.v2+json",
		Digest:    "sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c",
		Size:      528,
	}

	// exampleSignatureEnvelope is a valid signature envelope.
	exampleSignatureEnvelope := generateExampleSignatureEnvelope()

	// exampleVerifyOptions is an example of notation.VerifierVerifyOptions
	exampleVerifyOptions := notation.VerifierVerifyOptions{
		ArtifactReference:  exampleArtifactReference,
		SignatureMediaType: exampleSignatureMediaType,
	}

	// createTrustStore creates a trust store directory for demo purpose.
	// Users could use the default trust store from Notary and add trusted
	// certificates into it following the trust store spec:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-store
	if err := createTrustStore(); err != nil {
		panic(err) // Handle error
	}

	// exampleVerifier is an example of notation.Verifier given
	// trust policy document and X509 trust store.
	exampleVerifier, err := verifier.New(&examplePolicyDocument, truststore.NewX509TrustStore(dir.ConfigFS()), nil)
	if err != nil {
		panic(err) // Handle error
	}

	// local verify core process
	// upon successful verification, the signature verification outcome is
	// returned.
	outcome, err := exampleVerifier.Verify(context.Background(), exampleTargetDescriptor, exampleSignatureEnvelope, exampleVerifyOptions)
	if err != nil {
		panic(err) // Handle error
	}

	fmt.Println("Successfully verified")

	// a peek of the payload inside the signature envelope
	fmt.Println("payload ContentType:", outcome.EnvelopeContent.Payload.ContentType)

	// Note, upon successful verification, payload.TargetArtifact from the
	// signature envelope matches exactly with our exampleTargetDescriptor.
	// (This check has been done for the user inside verifier.Verify.)
	fmt.Println("payload Content:", string(outcome.EnvelopeContent.Payload.Content))

}

func generateExampleSignatureEnvelope() []byte {
	// exampleSignatureEnvelopePem is a valid signature envelope in COSE format
	// wrapped by a PEM block.
	// The signature envelope is generated in a previous Sign process.
	// Users should replace it with their own signature envelope.
	// Regarding how to generate such signature envelopes, users could refer to
	// `example_localSign_test.go`.
	exampleSignatureEnvelopePem := `-----BEGIN EXAMPLE SIGNATURE ENVELOPE-----
0oRYnqUBOCQCgXgcaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZQN4K2FwcGxp
Y2F0aW9uL3ZuZC5jbmNmLm5vdGFyeS5wYXlsb2FkLnYxK2pzb254GmlvLmNuY2Yu
bm90YXJ5LnNpZ25pbmdUaW1lwRpju22GeBxpby5jbmNmLm5vdGFyeS5zaWduaW5n
U2NoZW1la25vdGFyeS54NTA5ohghgVkDRDCCA0AwggIooAMCAQICAVEwDQYJKoZI
hvcNAQELBQAwTjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdT
ZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxDzANBgNVBAMTBmFscGluZTAgFw0wMDA4
MjkxMzUwMDBaGA8yMTIzMDgyOTEzNTAwMFowTjELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxDzANBgNV
BAMTBmFscGluZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKHIN6hL
MjQwy3wfDhw+HYYvjNTTytQLMuTV/OHPoL2nGbqDy08JqTn5upz7exjzwfRu0usc
YRTW0cU2H2FIyvpGgo9/F4wUX+ZRnsG0iSlZMUPNv2sVO9HHkltyaWs62oHjfSVE
2fyX4uDH54qSE8HJjKIoo/Hhqx7JI8lcmWyXdFjDCkQ1lYSz1IjzFVrf+He2LWSL
c2nGkCrV5l4LEwk1qSKJbN4H7TWI60KDLFHpVHQ/LzgFjfSdvP0sgvrkofytSn8l
JW6rn5+HYvAxAcZ7T+cJ12GyS9Y7Y7FIBMQFY0MU9cyOfV9+pt7d2CqgkIdXLndN
i+aJzm2Os4+ezekCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG
CCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQAvAIwS8uxLEaYuqILgnRUm+p0R
o7xdezfm+pg297AEZwfE9acb8009usmvgMlkfo46HRMGzCEvtd5Vfvak9i8KpWzl
DWOdfT2thkUWO9iY3qMFiN4ipCmjM32VAe5UUxl3RLmQKS20zv9yVXEfX37tNDdV
GgD/WBhJUreCQyWAPTPnf0LaPh4iLBNCo/o3Z8CGKLzzzpa8iji3xW/69RhKu5+t
8RWc/N4sljWmXbCeTd2B8XTqZGwWwmpThAQyU40CqngGAS6ADTVNDgbJZqhwkgUx
J4W6iRzekCshdPUnDpeS8DNULE5dFGObIhiwH4/40n/Th/VS0zxzkvPzdCmueBtp
by5jbmNmLm5vdGFyeS5zaWduaW5nQWdlbnRuTm90YXRpb24vMS4wLjBYtXsidGFy
Z2V0QXJ0aWZhY3QiOnsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tl
ci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsImRpZ2VzdCI6InNoYTI1
NjpjMGQ0ODhhODAwZTQxMjdjMzM0YWQyMGQ2MWQ3YmMyMWI0MDk3NTQwMzI3MjE3
ZGZhYjUyMjYyYWRjMDIzODBjIiwic2l6ZSI6NTI4fX1ZAQBUIYPA45B/iFylmloW
s/NpTVsheuedJb6nnXK0XR46BYs4AeCXVVYSRDK2Bq+tA9C7BXHoeCMcqnAHa8qs
ZR/fcMa9FrEPI6Pl8QVE/6QRMkT+Drn+9CSFxzHk6CU9S1vRsUVYNcibyejnuVEE
RPYaORrnfTc5wIs4XxeqprmrLimMMNn+u82Uadtc57tbHbY8Vh4XEKP++hBJJNvQ
E60X5aWKIS2RnOEc4n9T7LdN0bOL1OoM1lW4iTFMhzfcy/VmF8PrOStFS9LllX3J
69V0WwHbmD33cjtVBDCF44UXRWgLQGbE6yaaVmdxEUBGKqSUeHf8Gp7WoZ/YaFmz
xQr/
-----END EXAMPLE SIGNATURE ENVELOPE-----`

	block, _ := pem.Decode([]byte(exampleSignatureEnvelopePem))
	if block == nil {
		panic(errors.New("invalid signature envelope pem block"))
	}

	// block.Bytes contains the binary of the signature envelope.
	return block.Bytes
}

func createTrustStore() error {
	// changing the path of the trust store for demo purpose.
	// Users could keep the default value, i.e. os.UserConfigDir.
	dir.UserConfigDir = "tmp"

	// an example of a valid X509 self-signed certificate for demo purpose ONLY.
	// (This self-signed cert is paired with the private key used to
	// generate the `exampleSignatureEnvelopePem` above.)
	// Users should replace `exampleX509Certificate` with their own trusted
	// certificate and add to the trust store, following the
	// Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleX509Certificate := `-----BEGIN CERTIFICATE-----
MIIDQDCCAiigAwIBAgIBUTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEP
MA0GA1UEAxMGYWxwaW5lMCAXDTAwMDgyOTEzNTAwMFoYDzIxMjMwODI5MTM1MDAw
WjBOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUx
DzANBgNVBAoTBk5vdGFyeTEPMA0GA1UEAxMGYWxwaW5lMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAocg3qEsyNDDLfB8OHD4dhi+M1NPK1Asy5NX84c+g
vacZuoPLTwmpOfm6nPt7GPPB9G7S6xxhFNbRxTYfYUjK+kaCj38XjBRf5lGewbSJ
KVkxQ82/axU70ceSW3JpazrageN9JUTZ/Jfi4MfnipITwcmMoiij8eGrHskjyVyZ
bJd0WMMKRDWVhLPUiPMVWt/4d7YtZItzacaQKtXmXgsTCTWpIols3gftNYjrQoMs
UelUdD8vOAWN9J28/SyC+uSh/K1KfyUlbqufn4di8DEBxntP5wnXYbJL1jtjsUgE
xAVjQxT1zI59X36m3t3YKqCQh1cud02L5onObY6zj57N6QIDAQABoycwJTAOBgNV
HQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQAD
ggEBAC8AjBLy7EsRpi6oguCdFSb6nRGjvF17N+b6mDb3sARnB8T1pxvzTT26ya+A
yWR+jjodEwbMIS+13lV+9qT2LwqlbOUNY519Pa2GRRY72JjeowWI3iKkKaMzfZUB
7lRTGXdEuZApLbTO/3JVcR9ffu00N1UaAP9YGElSt4JDJYA9M+d/Qto+HiIsE0Kj
+jdnwIYovPPOlryKOLfFb/r1GEq7n63xFZz83iyWNaZdsJ5N3YHxdOpkbBbCalOE
BDJTjQKqeAYBLoANNU0OBslmqHCSBTEnhbqJHN6QKyF09ScOl5LwM1QsTl0UY5si
GLAfj/jSf9OH9VLTPHOS8/N0Ka4=
-----END CERTIFICATE-----`

	// Adding the certificate into the trust store.
	if err := os.MkdirAll("tmp/truststore/x509/ca/valid-trust-store", 0700); err != nil {
		return err
	}
	return os.WriteFile("tmp/truststore/x509/ca/valid-trust-store/NotationLocalExample.pem", []byte(exampleX509Certificate), 0600)
}
Output:
Successfully verified
payload ContentType: application/vnd.cncf.notary.payload.v1+json
payload Content: {"targetArtifact":{"mediaType":"application/vnd.docker.distribution.manifest.v2+json","digest":"sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c","size":528}}

ExampleRemoteSign demonstrates how to use notation.Sign to sign an artifact in the remote registry and push the signature to the remote.

package main

import (
	"context"
	"crypto/x509"
	"fmt"

	"oras.land/oras-go/v2/registry/remote"

	"github.com/notaryproject/notation-core-go/signature/cose"
	"github.com/notaryproject/notation-core-go/testhelper"
	"github.com/notaryproject/notation-go"
	"github.com/notaryproject/notation-go/registry"
	"github.com/notaryproject/notation-go/signer"
)

// Both COSE ("application/cose") and JWS ("application/jose+json")
// signature mediaTypes are supported.
var exampleSignatureMediaType = cose.MediaTypeEnvelope

// ExampleRemoteSign demonstrates how to use notation.Sign to sign an artifact
// in the remote registry and push the signature to the remote.
func main() {
	// exampleArtifactReference is an example of the target artifact reference
	var exampleArtifactReference = "localhost:5000/software@sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e"

	// exampleCertTuple contains a RSA privateKey and a self-signed X509
	// certificate generated for demo purpose ONLY.
	exampleCertTuple := testhelper.GetRSASelfSignedSigningCertTuple("Notation Example self-signed")
	exampleCerts := []*x509.Certificate{exampleCertTuple.Cert}

	// exampleSigner is a notation.Signer given key and X509 certificate chain.
	// Users should replace `exampleCertTuple.PrivateKey` with their own private
	// key and replace `exampleCerts` with the corresponding full certificate
	// chain, following the Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleSigner, err := signer.NewGenericSigner(exampleCertTuple.PrivateKey, exampleCerts)
	if err != nil {
		panic(err) // Handle error
	}

	// exampleRepo is an example of registry.Repository.
	remoteRepo, err := remote.NewRepository(exampleArtifactReference)
	if err != nil {
		panic(err) // Handle error
	}
	exampleRepo := registry.NewRepository(remoteRepo)

	// exampleSignOptions is an example of notation.SignOptions.
	exampleSignOptions := notation.SignOptions{
		SignerSignOptions: notation.SignerSignOptions{
			SignatureMediaType: exampleSignatureMediaType,
		},
		ArtifactReference: exampleArtifactReference,
	}

	// remote sign core process
	// upon successful signing, descriptor of the sign content is returned and
	// the generated signature is pushed into remote registry.
	targetDesc, err := notation.Sign(context.Background(), exampleSigner, exampleRepo, exampleSignOptions)
	if err != nil {
		panic(err) // Handle error
	}

	fmt.Println("Successfully signed")
	fmt.Println("targetDesc MediaType:", targetDesc.MediaType)
	fmt.Println("targetDesc Digest:", targetDesc.Digest)
	fmt.Println("targetDesc Size:", targetDesc.Size)
}

ExampleRemoteVerify demonstrates how to use notation.Verify to verify signatures of an artifact in the remote registry.

package main

import (
	"context"
	"fmt"
	"os"

	_ "github.com/notaryproject/notation-core-go/signature/cose"
	_ "github.com/notaryproject/notation-core-go/signature/jws"
	"github.com/notaryproject/notation-go"
	"github.com/notaryproject/notation-go/dir"
	"github.com/notaryproject/notation-go/registry"
	"github.com/notaryproject/notation-go/verifier"
	"github.com/notaryproject/notation-go/verifier/trustpolicy"
	"github.com/notaryproject/notation-go/verifier/truststore"
	"oras.land/oras-go/v2/registry/remote"
)

// ExampleRemoteVerify demonstrates how to use notation.Verify to verify
// signatures of an artifact in the remote registry.
func main() {
	// exampleArtifactReference is an example of the target artifact reference
	exampleArtifactReference := "localhost:5000/software@sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e"

	// examplePolicyDocument is an example of a valid trust policy document.
	// trust policy document should follow this spec:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy
	examplePolicyDocument := trustpolicy.Document{
		Version: "1.0",
		TrustPolicies: []trustpolicy.TrustPolicy{
			{
				Name:                  "test-statement-name",
				RegistryScopes:        []string{"*"},
				SignatureVerification: trustpolicy.SignatureVerification{VerificationLevel: trustpolicy.LevelStrict.Name},
				TrustStores:           []string{"ca:valid-trust-store"},
				TrustedIdentities:     []string{"*"},
			},
		},
	}

	// generateTrustStore generates a trust store directory for demo purpose.
	// Users should configure their own trust store and add trusted certificates
	// into it following the trust store spec:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-store
	if err := generateTrustStore(); err != nil {
		panic(err) // Handle error
	}

	// exampleVerifier is an example of notation.Verifier given
	// trust policy document and X509 trust store.
	exampleVerifier, err := verifier.New(&examplePolicyDocument, truststore.NewX509TrustStore(dir.ConfigFS()), nil)
	if err != nil {
		panic(err) // Handle error
	}

	// exampleRepo is an example of registry.Repository.
	remoteRepo, err := remote.NewRepository(exampleArtifactReference)
	if err != nil {
		panic(err) // Handle error
	}
	exampleRepo := registry.NewRepository(remoteRepo)

	// exampleVerifyOptions is an example of notation.VerifyOptions.
	exampleVerifyOptions := notation.VerifyOptions{
		ArtifactReference:    exampleArtifactReference,
		MaxSignatureAttempts: 50,
	}

	// remote verify core process
	// upon successful verification, the target manifest descriptor
	// and signature verification outcome are returned.
	targetDesc, _, err := notation.Verify(context.Background(), exampleVerifier, exampleRepo, exampleVerifyOptions)
	if err != nil {
		panic(err) // Handle error
	}

	fmt.Println("Successfully verified")
	fmt.Println("targetDesc MediaType:", targetDesc.MediaType)
	fmt.Println("targetDesc Digest:", targetDesc.Digest)
	fmt.Println("targetDesc Size:", targetDesc.Size)
}

func generateTrustStore() error {
	// changing the path of the trust store for demo purpose.
	// Users could keep the default value, i.e. os.UserConfigDir.
	dir.UserConfigDir = "tmp"

	// an example of a valid X509 self-signed certificate for demo purpose ONLY.
	// Users should replace `exampleX509Certificate` with their own trusted
	// certificate and add to the trust store, following the
	// Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleX509Certificate := `-----BEGIN CERTIFICATE-----
MIIDQDCCAiigAwIBAgIBUTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEP
MA0GA1UEAxMGYWxwaW5lMCAXDTAwMDgyOTEzNTAwMFoYDzIxMjMwODI5MTM1MDAw
WjBOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUx
DzANBgNVBAoTBk5vdGFyeTEPMA0GA1UEAxMGYWxwaW5lMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAocg3qEsyNDDLfB8OHD4dhi+M1NPK1Asy5NX84c+g
vacZuoPLTwmpOfm6nPt7GPPB9G7S6xxhFNbRxTYfYUjK+kaCj38XjBRf5lGewbSJ
KVkxQ82/axU70ceSW3JpazrageN9JUTZ/Jfi4MfnipITwcmMoiij8eGrHskjyVyZ
bJd0WMMKRDWVhLPUiPMVWt/4d7YtZItzacaQKtXmXgsTCTWpIols3gftNYjrQoMs
UelUdD8vOAWN9J28/SyC+uSh/K1KfyUlbqufn4di8DEBxntP5wnXYbJL1jtjsUgE
xAVjQxT1zI59X36m3t3YKqCQh1cud02L5onObY6zj57N6QIDAQABoycwJTAOBgNV
HQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQAD
ggEBAC8AjBLy7EsRpi6oguCdFSb6nRGjvF17N+b6mDb3sARnB8T1pxvzTT26ya+A
yWR+jjodEwbMIS+13lV+9qT2LwqlbOUNY519Pa2GRRY72JjeowWI3iKkKaMzfZUB
7lRTGXdEuZApLbTO/3JVcR9ffu00N1UaAP9YGElSt4JDJYA9M+d/Qto+HiIsE0Kj
+jdnwIYovPPOlryKOLfFb/r1GEq7n63xFZz83iyWNaZdsJ5N3YHxdOpkbBbCalOE
BDJTjQKqeAYBLoANNU0OBslmqHCSBTEnhbqJHN6QKyF09ScOl5LwM1QsTl0UY5si
GLAfj/jSf9OH9VLTPHOS8/N0Ka4=
-----END CERTIFICATE-----`

	// Adding the certificate into the trust store.
	if err := os.MkdirAll("tmp/truststore/x509/ca/valid-trust-store", 0700); err != nil {
		return err
	}
	return os.WriteFile("tmp/truststore/x509/ca/valid-trust-store/NotationExample.pem", []byte(exampleX509Certificate), 0600)
}

Example_signWithTimestamp demonstrates how to use notation.Sign to sign an artifact with a RFC 3161 compliant timestamp countersignature and user trusted TSA root certificate

// exampleArtifactReference is an example of the target artifact reference
var exampleArtifactReference = "localhost:5000/software@sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e"

// exampleCertTuple contains a RSA privateKey and a self-signed X509
// certificate generated for demo purpose ONLY.
exampleCertTuple := testhelper.GetRSASelfSignedSigningCertTuple("Notation Example self-signed")
exampleCerts := []*x509.Certificate{exampleCertTuple.Cert}

// exampleSigner is a notation.Signer given key and X509 certificate chain.
// Users should replace `exampleCertTuple.PrivateKey` with their own private
// key and replace `exampleCerts` with the corresponding full certificate
// chain, following the Notary certificate requirements:
// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
exampleSigner, err := signer.NewGenericSigner(exampleCertTuple.PrivateKey, exampleCerts)
if err != nil {
	panic(err) // Handle error
}

// exampleRepo is an example of registry.Repository.
remoteRepo, err := remote.NewRepository(exampleArtifactReference)
if err != nil {
	panic(err) // Handle error
}
exampleRepo := registry.NewRepository(remoteRepo)

// replace exampleRFC3161TSAServer with your trusted TSA server URL.
exampleRFC3161TSAServer := "<TSA server URL>"
httpTimestamper, err := tspclient.NewHTTPTimestamper(nil, exampleRFC3161TSAServer)
if err != nil {
	panic(err) // Handle error
}

// replace exampleTSARootCertPem with your trusted TSA root cert.
exampleTSARootCertPem := "<TSA root cert>"
block, _ := pem.Decode([]byte(exampleTSARootCertPem))
if block == nil {
	panic("failed to parse tsa root certificate PEM")
}
tsaRootCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
	panic("failed to parse tsa root certificate: " + err.Error())
}
tsaRootCAs := x509.NewCertPool()
tsaRootCAs.AddCert(tsaRootCert)

// enable timestamping certificate chain revocation check
tsaRevocationValidator, err := revocation.NewWithOptions(revocation.Options{
	CertChainPurpose: purpose.Timestamping,
})
if err != nil {
	panic(err) // Handle error
}

// exampleSignOptions is an example of notation.SignOptions.
exampleSignOptions := notation.SignOptions{
	SignerSignOptions: notation.SignerSignOptions{
		SignatureMediaType:     exampleSignatureMediaType,
		Timestamper:            httpTimestamper,
		TSARootCAs:             tsaRootCAs,
		TSARevocationValidator: tsaRevocationValidator,
	},
	ArtifactReference: exampleArtifactReference,
}

targetDesc, err := notation.Sign(context.Background(), exampleSigner, exampleRepo, exampleSignOptions)
if err != nil {
	panic(err) // Handle error
}

fmt.Println("Successfully signed")
fmt.Println("targetDesc MediaType:", targetDesc.MediaType)
fmt.Println("targetDesc Digest:", targetDesc.Digest)
fmt.Println("targetDesc Size:", targetDesc.Size)

Example_verifyWithTimestamp demonstrates how to use notation.Verify to verify signature of an artifact including RFC 3161 compliant timestamp countersignature

package main

import (
	"context"
	"fmt"
	"os"

	_ "github.com/notaryproject/notation-core-go/signature/cose"
	_ "github.com/notaryproject/notation-core-go/signature/jws"
	"github.com/notaryproject/notation-go"
	"github.com/notaryproject/notation-go/dir"
	"github.com/notaryproject/notation-go/registry"
	"github.com/notaryproject/notation-go/verifier"
	"github.com/notaryproject/notation-go/verifier/trustpolicy"
	"github.com/notaryproject/notation-go/verifier/truststore"
	"oras.land/oras-go/v2/registry/remote"
)

// Example_verifyWithTimestamp demonstrates how to use notation.Verify to verify
// signature of an artifact including RFC 3161 compliant timestamp countersignature
func main() {
	// exampleArtifactReference is an example of the target artifact reference
	exampleArtifactReference := "localhost:5000/software@sha256:60043cf45eaebc4c0867fea485a039b598f52fd09fd5b07b0b2d2f88fad9d74e"

	// examplePolicyDocument is an example of a valid trust policy document with
	// timestamping configurations.
	// trust policy document should follow this spec:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy
	examplePolicyDocument := trustpolicy.Document{
		Version: "1.0",
		TrustPolicies: []trustpolicy.TrustPolicy{
			{
				Name:           "test-statement-name",
				RegistryScopes: []string{"*"},
				SignatureVerification: trustpolicy.SignatureVerification{
					VerificationLevel: trustpolicy.LevelStrict.Name,

					// verify timestamp countersignature only if the signing
					// certificate chain has expired.
					// Default: trustpolicy.OptionAlways
					VerifyTimestamp: trustpolicy.OptionAfterCertExpiry,
				},

				// `tsa` trust store type MUST be configured to enable
				// timestamp verification
				TrustStores: []string{"ca:valid-trust-store", "tsa:valid-tsa"},

				// TrustedIdentities only contains trusted identities of `ca`
				// and `signingAuthority`
				TrustedIdentities: []string{"*"},
			},
		},
	}

	// generateTrustStoreWithTimestamp generates a trust store directory for demo purpose.
	// Users should configure their own trust store and add trusted certificates
	// into it following the trust store spec:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-store
	if err := generateTrustStoreWithTimestamp(); err != nil {
		panic(err) // Handle error
	}

	// exampleVerifier is an example of notation.Verifier given
	// trust policy document and X509 trust store.
	exampleVerifier, err := verifier.New(&examplePolicyDocument, truststore.NewX509TrustStore(dir.ConfigFS()), nil)
	if err != nil {
		panic(err) // Handle error
	}

	// exampleRepo is an example of registry.Repository.
	remoteRepo, err := remote.NewRepository(exampleArtifactReference)
	if err != nil {
		panic(err) // Handle error
	}
	exampleRepo := registry.NewRepository(remoteRepo)

	// exampleVerifyOptions is an example of notation.VerifyOptions.
	exampleVerifyOptions := notation.VerifyOptions{
		ArtifactReference:    exampleArtifactReference,
		MaxSignatureAttempts: 50,
	}

	// remote verify core process
	// upon successful verification, the target manifest descriptor
	// and signature verification outcome are returned.
	targetDesc, _, err := notation.Verify(context.Background(), exampleVerifier, exampleRepo, exampleVerifyOptions)
	if err != nil {
		panic(err) // Handle error
	}

	fmt.Println("Successfully verified")
	fmt.Println("targetDesc MediaType:", targetDesc.MediaType)
	fmt.Println("targetDesc Digest:", targetDesc.Digest)
	fmt.Println("targetDesc Size:", targetDesc.Size)
}

func generateTrustStoreWithTimestamp() error {
	// changing the path of the trust store for demo purpose.
	// Users could keep the default value, i.e. os.UserConfigDir.
	dir.UserConfigDir = "tmp"

	// an example of a valid X509 self-signed certificate for demo purpose ONLY.
	// Users should replace `exampleX509Certificate` with their own trusted
	// certificate and add to the trust store, following the
	// Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleX509Certificate := `-----BEGIN CERTIFICATE-----
MIIDQDCCAiigAwIBAgIBUTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEP
MA0GA1UEAxMGYWxwaW5lMCAXDTAwMDgyOTEzNTAwMFoYDzIxMjMwODI5MTM1MDAw
WjBOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUx
DzANBgNVBAoTBk5vdGFyeTEPMA0GA1UEAxMGYWxwaW5lMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAocg3qEsyNDDLfB8OHD4dhi+M1NPK1Asy5NX84c+g
vacZuoPLTwmpOfm6nPt7GPPB9G7S6xxhFNbRxTYfYUjK+kaCj38XjBRf5lGewbSJ
KVkxQ82/axU70ceSW3JpazrageN9JUTZ/Jfi4MfnipITwcmMoiij8eGrHskjyVyZ
bJd0WMMKRDWVhLPUiPMVWt/4d7YtZItzacaQKtXmXgsTCTWpIols3gftNYjrQoMs
UelUdD8vOAWN9J28/SyC+uSh/K1KfyUlbqufn4di8DEBxntP5wnXYbJL1jtjsUgE
xAVjQxT1zI59X36m3t3YKqCQh1cud02L5onObY6zj57N6QIDAQABoycwJTAOBgNV
HQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQAD
ggEBAC8AjBLy7EsRpi6oguCdFSb6nRGjvF17N+b6mDb3sARnB8T1pxvzTT26ya+A
yWR+jjodEwbMIS+13lV+9qT2LwqlbOUNY519Pa2GRRY72JjeowWI3iKkKaMzfZUB
7lRTGXdEuZApLbTO/3JVcR9ffu00N1UaAP9YGElSt4JDJYA9M+d/Qto+HiIsE0Kj
+jdnwIYovPPOlryKOLfFb/r1GEq7n63xFZz83iyWNaZdsJ5N3YHxdOpkbBbCalOE
BDJTjQKqeAYBLoANNU0OBslmqHCSBTEnhbqJHN6QKyF09ScOl5LwM1QsTl0UY5si
GLAfj/jSf9OH9VLTPHOS8/N0Ka4=
-----END CERTIFICATE-----`

	// Adding the certificate into the trust store.
	if err := os.MkdirAll("tmp/truststore/x509/ca/valid-trust-store", 0700); err != nil {
		return err
	}
	if err := os.WriteFile("tmp/truststore/x509/ca/valid-trust-store/NotationExample.pem", []byte(exampleX509Certificate), 0600); err != nil {
		return err
	}

	// an example of a valid TSA root certificate for demo purpose ONLY.
	// Users should replace `exampleTSARootCertificate` with their own trusted
	// TSA root certificate and add to the trust store, following the
	// Notary certificate requirements:
	// https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements
	exampleTSARootCertificate := `-----BEGIN CERTIFICATE-----
		MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
		MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
		d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
		RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
		UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
		Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
		SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
		ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
		xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
		ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
		DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
		jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
		CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
		EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
		fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
		uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
		chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
		9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
		hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
		ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
		SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
		+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
		fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
		sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
		cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
		0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
		4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
		r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
		/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
		gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
		-----END CERTIFICATE-----`

	// Adding the tsa root certificate into the trust store.
	if err := os.MkdirAll("tmp/truststore/x509/tsa/valid-tsa", 0700); err != nil {
		return err
	}
	return os.WriteFile("tmp/truststore/x509/tsa/valid-tsa/NotationTSAExample.pem", []byte(exampleTSARootCertificate), 0600)
}

This section is empty.

This section is empty.

Sign signs the OCI artifact and push the signature to the Repository. The descriptor of the sign content is returned upon successful signing.

type ErrorNoApplicableTrustPolicy = NoApplicableTrustPolicyError

ErrorNoApplicableTrustPolicy is used when there is no trust policy that applies to the given artifact

Deprecated: Use NoApplicableTrustPolicyError instead.

type ErrorPushSignatureFailed = PushSignatureFailedError

ErrorPushSignatureFailed is used when failed to push signature to the target registry.

Deprecated: Use PushSignatureFailedError instead.

type ErrorSignatureRetrievalFailed = SignatureRetrievalFailedError

ErrorSignatureRetrievalFailed is used when notation is unable to retrieve the digital signature/s for the given artifact

Deprecated: Use SignatureRetrievalFailedError instead.

type ErrorUserMetadataVerificationFailed = UserMetadataVerificationFailedError

ErrorUserMetadataVerificationFailed is used when the signature does not contain the user specified metadata

Deprecated: Use UserMetadataVerificationFailedError instead.

type ErrorVerificationFailed = VerificationFailedError

ErrorVerificationFailed is used when it is determined that the digital signature/s is not valid for the given artifact

Deprecated: Use VerificationFailedError instead.

type ErrorVerificationInconclusive = VerificationInconclusiveError

ErrorVerificationInconclusive is used when signature verification fails due to a runtime error (e.g. a network error)

Deprecated: Use VerificationInconclusiveError instead.

type NoApplicableTrustPolicyError struct {
	Msg string
}

NoApplicableTrustPolicyError is used when there is no trust policy that applies to the given artifact

type PushSignatureFailedError struct {
	Msg string
}

PushSignatureFailedError is used when failed to push signature to the target registry.

SignOptions contains parameters for notation.Sign.

type SignatureRetrievalFailedError struct {
	Msg string
}

SignatureRetrievalFailedError is used when notation is unable to retrieve the digital signature/s for the given artifact

Signer is a generic interface for signing an OCI artifact. The interface allows signing with local or remote keys, and packing in various signature formats.

SignerSignOptions contains parameters for Signer.Sign.

type UserMetadataVerificationFailedError struct {
	Msg string
}

UserMetadataVerificationFailedError is used when the signature does not contain the user specified metadata

ValidationResult encapsulates the verification result (passed or failed) for a verification type, including the desired verification action as specified in the trust policy

type VerificationFailedError struct {
	Msg string
}

VerificationFailedError is used when it is determined that the digital signature/s is not valid for the given artifact

type VerificationInconclusiveError struct {
	Msg string
}

VerificationInconclusiveError is used when signature verification fails due to a runtime error (e.g. a network error)

VerificationOutcome encapsulates a signature envelope blob, its content, the verification level and results for each verification type that was performed.

Verifier is a interface for verifying an OCI artifact.

VerifierVerifyOptions contains parameters for Verifier.Verify used for verifying OCI artifact.

VerifyOptions contains parameters for notation.Verify.