Documentation
¶
Overview ¶
Package notation provides signer and verifier for notation Sign and Verification. It supports both OCI artifact and arbitrary blob.
Example (LocalSign) ¶
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 Project 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
Example (LocalVerify) ¶
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.OCIDocument{ Version: "1.0", TrustPolicies: []trustpolicy.OCITrustPolicy{ { 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 Project 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 Project 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}}
Example (RemoteSign) ¶
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 Project 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. targetManifestDesc, sigManifestDesc, err := notation.SignOCI(context.Background(), exampleSigner, exampleRepo, exampleSignOptions) if err != nil { panic(err) // Handle error } fmt.Println("Successfully signed") fmt.Println("targetManifestDesc.MediaType:", targetManifestDesc.MediaType) fmt.Println("targetManifestDesc.Digest:", targetManifestDesc.Digest) fmt.Println("targetManifestDesc.Size:", targetManifestDesc.Size) fmt.Println("sigManifestDesc.MediaType:", sigManifestDesc.MediaType) fmt.Println("sigManifestDesc.Digest:", sigManifestDesc.Digest) fmt.Println("sigManifestDesc.Size:", sigManifestDesc.Size) }
Example (RemoteVerify) ¶
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.OCIDocument{ Version: "1.0", TrustPolicies: []trustpolicy.OCITrustPolicy{ { 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 Project 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 (SignBlob) ¶
ExampleSignBlob demonstrates how to use notation.SignBlob to sign arbitrary data.
// exampleSigner implements [notation.Signer] and [notation.BlobSigner]. // Given key and X509 certificate chain, it provides method to sign OCI // artifacts or blobs. // Users should replace `exampleCertTuple.PrivateKey` with their own private // key and replace `exampleCerts` with the corresponding certificate chain, // following the Notary Project certificate requirements: // https://github.com/notaryproject/specifications/tree/9c81dc773508dedc5a81c02c8d805de04f65050b/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 := jws.MediaTypeEnvelope exampleContentMediaType := "video/mp4" // exampleSignOptions is an example of [notation.SignBlobOptions]. exampleSignOptions := notation.SignBlobOptions{ SignerSignOptions: notation.SignerSignOptions{ SignatureMediaType: exampleSignatureMediaType, SigningAgent: "example signing agent", }, ContentMediaType: exampleContentMediaType, UserMetadata: map[string]string{"buildId": "101"}, } // exampleReader reads the data that needs to be signed. // This data can be in a file or in memory. exampleReader := strings.NewReader("example blob") // Upon successful signing, signature envelope and signerInfo are returned. // signatureEnvelope can be used in a verification process later on. signatureEnvelope, signerInfo, err := notation.SignBlob(context.Background(), exampleSigner, exampleReader, exampleSignOptions) if err != nil { panic(err) // Handle error } fmt.Println("Successfully signed") // a peek of the signature envelope generated 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":{"annotations":{"buildId":"101"},"digest":"sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61","mediaType":"video/mp4","size":12}} signerInfo SigningAgent: example signing agent
Example (SignWithTimestamp) ¶
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 Project 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, } targetManifestDesc, sigManifestDesc, err := notation.SignOCI(context.Background(), exampleSigner, exampleRepo, exampleSignOptions) if err != nil { panic(err) // Handle error } fmt.Println("Successfully signed") fmt.Println("targetManifestDesc.MediaType:", targetManifestDesc.MediaType) fmt.Println("targetManifestDesc.Digest:", targetManifestDesc.Digest) fmt.Println("targetManifestDesc.Size:", targetManifestDesc.Size) fmt.Println("sigManifestDesc.MediaType:", sigManifestDesc.MediaType) fmt.Println("sigManifestDesc.Digest:", sigManifestDesc.Digest) fmt.Println("sigManifestDesc.Size:", sigManifestDesc.Size)
Example (VerifyBlob) ¶
ExampleVerifyBlob demonstrates how to use notation.VerifyBlob to verify a signature of an arbitrary blob.
package main import ( "context" "fmt" "os" "strings" "github.com/notaryproject/notation-core-go/signature/jws" "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" ) // exampleBlobPolicyDocument is an example of a valid blob trust policy document. // blob trust policy document should follow this spec: // https://github.com/notaryproject/specifications/tree/9c81dc773508dedc5a81c02c8d805de04f65050b/specs/trust-store-trust-policy.md#blob-trust-policy var exampleBlobPolicyDocument = trustpolicy.BlobDocument{ Version: "1.0", TrustPolicies: []trustpolicy.BlobTrustPolicy{ { Name: "test-statement-name", 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{"*"}, }, }, } // ExampleVerifyBlob demonstrates how to use [notation.VerifyBlob] to verify a // signature of an arbitrary blob. func main() { // Both COSE ("application/cose") and JWS ("application/jose+json") // signature mediaTypes are supported. exampleSignatureMediaType := jws.MediaTypeEnvelope // exampleSignatureEnvelope is a valid signature envelope. exampleSignatureEnvelope := getSignatureEnvelope() // createTrustStoreForBlobVerify creates a trust store directory for demo purpose. // Users could use the default trust store from Notary Project and add trusted // certificates into it following the trust store spec: // https://github.com/notaryproject/specifications/tree/9c81dc773508dedc5a81c02c8d805de04f65050b/specs/trust-store-trust-policy.md#trust-store if err := createTrustStoreForBlobVerify(); err != nil { panic(err) // Handle error } // exampleVerifier implements [notation.Verify] and [notation.VerifyBlob]. exampleVerifier, err := verifier.NewVerifierWithOptions(truststore.NewX509TrustStore(dir.ConfigFS()), verifier.VerifierOptions{ BlobTrustPolicy: &exampleBlobPolicyDocument, }) if err != nil { panic(err) // Handle error } // exampleReader reads the data that needs to be verified. // This data can be in a file or in memory. exampleReader := strings.NewReader("example blob") // exampleVerifyOptions is an example of [notation.VerifyBlobOptions] exampleVerifyOptions := notation.VerifyBlobOptions{ BlobVerifierVerifyOptions: notation.BlobVerifierVerifyOptions{ SignatureMediaType: exampleSignatureMediaType, TrustPolicyName: "test-statement-name", }, } // upon successful verification, the signature verification outcome is // returned. _, outcome, err := notation.VerifyBlob(context.Background(), exampleVerifier, exampleReader, []byte(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 createTrustStoreForBlobVerify() 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 Project certificate requirements: // https://github.com/notaryproject/specifications/tree/9c81dc773508dedc5a81c02c8d805de04f65050b/specs/signature-specification.md#certificate-requirements exampleX509Certificate := `-----BEGIN CERTIFICATE----- MIIEbDCCAtSgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzEL MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEl MCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAgFw0yNDA0MDQy MTIwMjBaGA8yMTI0MDQwNDIxMjAyMFowZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT AldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxJTAjBgNVBAMT HE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwggGiMA0GCSqGSIb3DQEBAQUA A4IBjwAwggGKAoIBgQDGIiN4yCjSVqFELZwxK/BMb8BokP587L8oPrZ1g8H7LudB moLNDT7vF9xccbCfU3yNuOd0WaOgnENiCs81VHidyJsj1Oz3u+0Zn3ng7V+uZr6m AIO74efA9ClMiY4i4HIt8IAZF57AL2mzDnCITgSWxikf030Il85MI42STvA+qYuz ZEOp3XvKo8bDgQFvbtgK0HYYMfrka7VDmIWVo0rBMGm5btI8HOYQ0r9aqsrCxLAv 1AQeOQm+wbRcp4R5PIUJr+REGn7JCbOyXg/7qqHXKKmvV5yrGaraw8gZ5pqP/RHK XUJIfvD0Vf2epJmsvC+6vXkSWtz+cA8J4GQx4J4SXL57hoYkC5qv39SOLzlWls3I 6fgeO+SZ0sceMd8NKlom/L5eOJBfB3bTQB83hq/3bRtjT7/qCMsL3VcndKkS+vGF JPw5uTH+pmBgHrLr6tRoRRjwRFuZ0dO05AbdjCaxgVDtFI3wNbaXn/1VlRGySQIS UNWxCrUsSzndeqwmjqsCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM MAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBgQBdi0SaJAaeKBB0I+Fjcbmc 4zRvHE4GDSMSDnAK97nrZCZ9iwKuY4x6mv9lwQe2P3VXROoL9JmONNf0yaObOwQj ILGnbe2rzYtUardz2gzh+6KNzJHspRvk1f06mp4496XQ3STMRSr8kno1svKQMy0Y FRsGMKs4fWHavIAqNXg9ymrZvvXiatN2UiVtAA/jBFScZAWskeb2WHNzORi7H5Z1 mp5+IlNYQpzdIu/dvLVxzhh2UvkRdsQqsMgt/MOU84RncwUNZM4yI5EGPoaSJdsj AGNd+UV6ur7QmVI2Q9EZNRlaDJtaoZmKns5j1SlmDXWKbdRmw42ORDudODj/pHA9 +u+ca9t3uLsbqO9yPm8m+6fyxffWS11QAH6O7EjydJWcEe5tYkPpL6kcaEyQKESm 5CDlsk+W3ElpaUu6tsnGKODvgdAN3m0noC+qxzCMqoCM4+M5V6OptR98MDl2FK0B 5+WF6YHBxf/uqDvFktUczjrIWuyfECywp05bpGAErGE= -----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/NotationBlobExample.pem", []byte(exampleX509Certificate), 0600) } func getSignatureEnvelope() string { return `{"payload":"eyJ0YXJnZXRBcnRpZmFjdCI6eyJkaWdlc3QiOiJzaGEzODQ6YjhhYjI0ZGFmYmE1Y2Y3ZTRjODljNTYyZjgxMWNmMTA0OTNkNDIwM2RhOTgyZDNiMTM0NWYzNjZjYTg2M2Q5YzJlZDMyM2RiZDBmYjdmZjgzYTgwMzAyY2VmZmE1YTYxIiwibWVkaWFUeXBlIjoidmlkZW8vbXA0Iiwic2l6ZSI6MTJ9fQ","protected":"eyJhbGciOiJQUzM4NCIsImNyaXQiOlsiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSJdLCJjdHkiOiJhcHBsaWNhdGlvbi92bmQuY25jZi5ub3RhcnkucGF5bG9hZC52MStqc29uIiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSI6Im5vdGFyeS54NTA5IiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1RpbWUiOiIyMDI0LTA0LTA0VDE0OjIwOjIxLTA3OjAwIn0","header":{"x5c":["MIIEbDCCAtSgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTElMCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAgFw0yNDA0MDQyMTIwMjBaGA8yMTI0MDQwNDIxMjAyMFowZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxJTAjBgNVBAMTHE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDGIiN4yCjSVqFELZwxK/BMb8BokP587L8oPrZ1g8H7LudBmoLNDT7vF9xccbCfU3yNuOd0WaOgnENiCs81VHidyJsj1Oz3u+0Zn3ng7V+uZr6mAIO74efA9ClMiY4i4HIt8IAZF57AL2mzDnCITgSWxikf030Il85MI42STvA+qYuzZEOp3XvKo8bDgQFvbtgK0HYYMfrka7VDmIWVo0rBMGm5btI8HOYQ0r9aqsrCxLAv1AQeOQm+wbRcp4R5PIUJr+REGn7JCbOyXg/7qqHXKKmvV5yrGaraw8gZ5pqP/RHKXUJIfvD0Vf2epJmsvC+6vXkSWtz+cA8J4GQx4J4SXL57hoYkC5qv39SOLzlWls3I6fgeO+SZ0sceMd8NKlom/L5eOJBfB3bTQB83hq/3bRtjT7/qCMsL3VcndKkS+vGFJPw5uTH+pmBgHrLr6tRoRRjwRFuZ0dO05AbdjCaxgVDtFI3wNbaXn/1VlRGySQISUNWxCrUsSzndeqwmjqsCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBgQBdi0SaJAaeKBB0I+Fjcbmc4zRvHE4GDSMSDnAK97nrZCZ9iwKuY4x6mv9lwQe2P3VXROoL9JmONNf0yaObOwQjILGnbe2rzYtUardz2gzh+6KNzJHspRvk1f06mp4496XQ3STMRSr8kno1svKQMy0YFRsGMKs4fWHavIAqNXg9ymrZvvXiatN2UiVtAA/jBFScZAWskeb2WHNzORi7H5Z1mp5+IlNYQpzdIu/dvLVxzhh2UvkRdsQqsMgt/MOU84RncwUNZM4yI5EGPoaSJdsjAGNd+UV6ur7QmVI2Q9EZNRlaDJtaoZmKns5j1SlmDXWKbdRmw42ORDudODj/pHA9+u+ca9t3uLsbqO9yPm8m+6fyxffWS11QAH6O7EjydJWcEe5tYkPpL6kcaEyQKESm5CDlsk+W3ElpaUu6tsnGKODvgdAN3m0noC+qxzCMqoCM4+M5V6OptR98MDl2FK0B5+WF6YHBxf/uqDvFktUczjrIWuyfECywp05bpGAErGE="],"io.cncf.notary.signingAgent":"example signing agent"},"signature":"liOjdgQ9BKuQTZGXRh3o6P8AMUIq_MKQReEcqA5h8M4RYs3DV_wXfaLCr2x_NRcwjTZsoO1_J77hmzkkk4L0IuFP8Qw0KKtmc83G0yFi4yYV5fwzrIbnhC2GRLuqLPnK-C4qYmv52ld3ebvo7XWwRHu30-VXePmTRFp6iG-eSAgkNgwhxSZ0ZmTFLG3ceNiX2bxpLHlXdPwA3aFKbd6nKrzo4CZ1ZyLNmAIaoA5-kmc0Hyt45trpxaaiWusI_pcTLw71YCqEAs32tEq3q6hRAgAZZN-Qvm9GyNp9EuaPiKjMbJFqtjome5ITxyNd-5t09dDCUgSe3t-iqv2Blm4E080AP1TYwUKLYklGniUP1dAtOau5G2juZLpl7tr4LQ99mycflnAmV7e79eEWXffvy5EAl77dW4_vM7lEemm08m2wddGuDOWXYb1j1r2_a5Xb92umHq6ZMhAp200A0pUkm9640x8z5jdudi_7KeezdqUK7ZMmSxHohiylyKD_20Cy"}` }
Output: Successfully verified payload ContentType: application/vnd.cncf.notary.payload.v1+json payload Content: {"targetArtifact":{"digest":"sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61","mediaType":"video/mp4","size":12}}
Example (VerifyWithTimestamp) ¶
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.OCIDocument{ Version: "1.0", TrustPolicies: []trustpolicy.OCITrustPolicy{ { 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 Project 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 Project 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) }
Index ¶
- func Sign(ctx context.Context, signer Signer, repo registry.Repository, ...) (ocispec.Descriptor, error)deprecated
- func SignBlob(ctx context.Context, signer BlobSigner, blobReader io.Reader, ...) ([]byte, *signature.SignerInfo, error)
- func SignOCI(ctx context.Context, signer Signer, repo registry.Repository, ...) (artifactManifestDesc, sigManifestDesc ocispec.Descriptor, err error)
- type BlobDescriptorGenerator
- type BlobSigner
- type BlobVerifier
- type BlobVerifierVerifyOptions
- type ErrorNoApplicableTrustPolicydeprecated
- type ErrorPushSignatureFaileddeprecated
- type ErrorSignatureRetrievalFaileddeprecated
- type ErrorUserMetadataVerificationFaileddeprecated
- type ErrorVerificationFaileddeprecated
- type ErrorVerificationInconclusivedeprecated
- type NoApplicableTrustPolicyError
- type PushSignatureFailedError
- type SignBlobOptions
- type SignOptions
- type SignatureRetrievalFailedError
- type Signer
- type SignerSignOptions
- type UserMetadataVerificationFailedError
- type ValidationResult
- type VerificationFailedError
- type VerificationInconclusiveError
- type VerificationOutcome
- type Verifier
- type VerifierVerifyOptions
- type VerifyBlobOptions
- type VerifyOptions
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Sign
deprecated
func Sign(ctx context.Context, signer Signer, repo registry.Repository, signOpts SignOptions) (ocispec.Descriptor, error)
Sign signs the OCI artifact and push the signature to the Repository. The descriptor of the sign content is returned upon successful signing.
Deprecated: use SignOCI instead.
func SignBlob ¶
func SignBlob(ctx context.Context, signer BlobSigner, blobReader io.Reader, signBlobOpts SignBlobOptions) ([]byte, *signature.SignerInfo, error)
SignBlob signs the arbitrary data from blobReader and returns the signature and SignerInfo.
func SignOCI ¶
func SignOCI(ctx context.Context, signer Signer, repo registry.Repository, signOpts SignOptions) (artifactManifestDesc, sigManifestDesc ocispec.Descriptor, err error)
SignOCI signs the OCI artifact and push the signature to the Repository.
Both artifact and signature manifest descriptors are returned upon successful signing.
Note: If the error type is remote.ReferrersError and referrerError.IsReferrersIndexDelete() returns true, the signature is successfully pushed to the repository, but the referrers index deletion failed. In this case, the artifact and signature manifest descriptors are returned with the error.
Types ¶
type BlobDescriptorGenerator ¶
type BlobDescriptorGenerator func(digest.Algorithm) (ocispec.Descriptor, error)
BlobDescriptorGenerator creates descriptor using the digest Algorithm. Below is the example of minimal descriptor, it must contain mediatype, digest and size of the artifact.
{ "mediaType": "application/octet-stream", "digest": "sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345", "size": 1024 }
type BlobSigner ¶
type BlobSigner interface { // SignBlob signs the descriptor returned by genDesc, and returns the // signature and SignerInfo. SignBlob(ctx context.Context, genDesc BlobDescriptorGenerator, opts SignerSignOptions) ([]byte, *signature.SignerInfo, error) }
BlobSigner is a generic interface for signing arbitrary data. The interface allows signing with local or remote keys, and packing in various signature formats.
type BlobVerifier ¶
type BlobVerifier interface { // VerifyBlob verifies the `signature` against the target blob using the // descriptor returned by descGenFunc parameter and // returns the outcome upon successful verification. VerifyBlob(ctx context.Context, descGenFunc BlobDescriptorGenerator, signature []byte, opts BlobVerifierVerifyOptions) (*VerificationOutcome, error) }
BlobVerifier is a generic interface for verifying a blob.
type BlobVerifierVerifyOptions ¶
type BlobVerifierVerifyOptions struct { // SignatureMediaType is the envelope type of the signature. // Currently only `application/jose+json` and `application/cose` are // supported. SignatureMediaType string // PluginConfig is a map of plugin configs. PluginConfig map[string]string // UserMetadata contains key-value pairs that must be present in the // signature. UserMetadata map[string]string // TrustPolicyName is the name of trust policy picked by caller. // If empty, the global trust policy will be applied. TrustPolicyName string }
BlobVerifierVerifyOptions contains parameters for [BlobVerifier.Verify].
type ErrorNoApplicableTrustPolicy
deprecated
type ErrorNoApplicableTrustPolicy = NoApplicableTrustPolicyError
ErrorNoApplicableTrustPolicy is used when there is no trust policy that applies to the given artifact
Deprecated: Use NoApplicableTrustPolicyError instead.
type ErrorPushSignatureFailed
deprecated
type ErrorPushSignatureFailed = PushSignatureFailedError
ErrorPushSignatureFailed is used when failed to push signature to the target registry.
Deprecated: Use PushSignatureFailedError instead.
type ErrorSignatureRetrievalFailed
deprecated
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
deprecated
type ErrorUserMetadataVerificationFailed = UserMetadataVerificationFailedError
ErrorUserMetadataVerificationFailed is used when the signature does not contain the user specified metadata
Deprecated: Use UserMetadataVerificationFailedError instead.
type ErrorVerificationFailed
deprecated
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
deprecated
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 ¶ added in v1.3.2
type NoApplicableTrustPolicyError struct {
Msg string
}
NoApplicableTrustPolicyError is used when there is no trust policy that applies to the given artifact
func (NoApplicableTrustPolicyError) Error ¶ added in v1.3.2
func (e NoApplicableTrustPolicyError) Error() string
type PushSignatureFailedError ¶ added in v1.3.2
type PushSignatureFailedError struct {
Msg string
}
PushSignatureFailedError is used when failed to push signature to the target registry.
func (PushSignatureFailedError) Error ¶ added in v1.3.2
func (e PushSignatureFailedError) Error() string
type SignBlobOptions ¶
type SignBlobOptions struct { SignerSignOptions // ContentMediaType is the media-type of the blob being signed. ContentMediaType string // UserMetadata contains key-value pairs that are added to the signature // payload UserMetadata map[string]string }
SignBlobOptions contains parameters for notation.SignBlob.
type SignOptions ¶
type SignOptions struct { SignerSignOptions // ArtifactReference sets the reference of the artifact that needs to be // signed. It can be a tag, a digest or a full reference. ArtifactReference string // UserMetadata contains key-value pairs that are added to the signature // payload UserMetadata map[string]string }
SignOptions contains parameters for notation.Sign.
type SignatureRetrievalFailedError ¶ added in v1.3.2
type SignatureRetrievalFailedError struct {
Msg string
}
SignatureRetrievalFailedError is used when notation is unable to retrieve the digital signature/s for the given artifact
func (SignatureRetrievalFailedError) Error ¶ added in v1.3.2
func (e SignatureRetrievalFailedError) Error() string
type Signer ¶
type Signer interface { // Sign signs the OCI artifact described by its descriptor, // and returns the signature and SignerInfo. Sign(ctx context.Context, desc ocispec.Descriptor, opts SignerSignOptions) ([]byte, *signature.SignerInfo, error) }
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.
type SignerSignOptions ¶
type SignerSignOptions struct { // SignatureMediaType is the envelope type of the signature. // Currently, both `application/jose+json` and `application/cose` are // supported. SignatureMediaType string // ExpiryDuration identifies the expiry duration of the resulted signature. // Zero value represents no expiry duration. ExpiryDuration time.Duration // PluginConfig sets or overrides the plugin configuration. PluginConfig map[string]string // SigningAgent sets the signing agent name SigningAgent string // Timestamper denotes the timestamper for RFC 3161 timestamping Timestamper tspclient.Timestamper // TSARootCAs is the cert pool holding caller's TSA trust anchor TSARootCAs *x509.CertPool // TSARevocationValidator is used for validating revocation status of // timestamping certificate chain with context during signing. // When present, only used when timestamping is performed. TSARevocationValidator revocation.Validator }
SignerSignOptions contains parameters for Signer and BlobSigner.
type UserMetadataVerificationFailedError ¶ added in v1.3.2
type UserMetadataVerificationFailedError struct {
Msg string
}
UserMetadataVerificationFailedError is used when the signature does not contain the user specified metadata
func (UserMetadataVerificationFailedError) Error ¶ added in v1.3.2
func (e UserMetadataVerificationFailedError) Error() string
type ValidationResult ¶
type ValidationResult struct { // Type of verification that is performed Type trustpolicy.ValidationType // Action is the intended action for the given verification type as defined // in the trust policy Action trustpolicy.ValidationAction // Error is set if there are any errors during the verification process Error error }
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 ¶ added in v1.3.2
type VerificationFailedError struct {
Msg string
}
VerificationFailedError is used when it is determined that the digital signature/s is not valid for the given artifact
func (VerificationFailedError) Error ¶ added in v1.3.2
func (e VerificationFailedError) Error() string
type VerificationInconclusiveError ¶ added in v1.3.2
type VerificationInconclusiveError struct {
Msg string
}
VerificationInconclusiveError is used when signature verification fails due to a runtime error (e.g. a network error)
func (VerificationInconclusiveError) Error ¶ added in v1.3.2
func (e VerificationInconclusiveError) Error() string
type VerificationOutcome ¶
type VerificationOutcome struct { // RawSignature is the signature envelope blob RawSignature []byte // EnvelopeContent contains the details of the digital signature and // associated metadata EnvelopeContent *signature.EnvelopeContent // VerificationLevel describes what verification level was used for // performing signature verification VerificationLevel *trustpolicy.VerificationLevel // VerificationResults contains the verifications performed on the signature // and their results VerificationResults []*ValidationResult // Error that caused the verification to fail (if it fails) Error error }
VerificationOutcome encapsulates a signature envelope blob, its content, the verification level and results for each verification type that was performed.
func Verify ¶
func Verify(ctx context.Context, verifier Verifier, repo registry.Repository, verifyOpts VerifyOptions) (ocispec.Descriptor, []*VerificationOutcome, error)
Verify performs signature verification on each of the notation supported verification types (like integrity, authenticity, etc.) and returns the successful signature verification outcome. For more details on signature verification, see https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md#signature-verification
func VerifyBlob ¶
func VerifyBlob(ctx context.Context, blobVerifier BlobVerifier, blobReader io.Reader, signature []byte, verifyBlobOpts VerifyBlobOptions) (ocispec.Descriptor, *VerificationOutcome, error)
VerifyBlob performs signature verification for a blob using notation supported verification types (like integrity, authenticity, etc.) and returns the successful signature verification outcome. The blob is read using blobReader, and upon successful verification, it returns the descriptor of the blob. For more details on signature verification, see https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md#signature-verification
func (*VerificationOutcome) UserMetadata ¶
func (outcome *VerificationOutcome) UserMetadata() (map[string]string, error)
UserMetadata returns the user metadata from the signature envelope.
type Verifier ¶
type Verifier interface { // Verify verifies the `signature` associated with the target OCI artifact // with manifest descriptor `desc`, and returns the outcome upon // successful verification. // If nil signature is present and the verification level is not 'skip', // an error will be returned. Verify(ctx context.Context, desc ocispec.Descriptor, signature []byte, opts VerifierVerifyOptions) (*VerificationOutcome, error) }
Verifier is a generic interface for verifying an OCI artifact.
type VerifierVerifyOptions ¶
type VerifierVerifyOptions struct { // ArtifactReference is the reference of the artifact that is being // verified against to. It must be a full reference. ArtifactReference string // SignatureMediaType is the envelope type of the signature. // Currently only `application/jose+json` and `application/cose` are // supported. SignatureMediaType string // PluginConfig is a map of plugin configs. PluginConfig map[string]string // UserMetadata contains key-value pairs that must be present in the // signature. UserMetadata map[string]string }
VerifierVerifyOptions contains parameters for [Verifier.Verify] used for verifying OCI artifact.
type VerifyBlobOptions ¶
type VerifyBlobOptions struct { BlobVerifierVerifyOptions // ContentMediaType is the media-type type of the content being verified. ContentMediaType string }
VerifyBlobOptions contains parameters for notation.VerifyBlob.
type VerifyOptions ¶
type VerifyOptions struct { // ArtifactReference is the reference of the artifact that is being // verified against to. ArtifactReference string // PluginConfig is a map of plugin configs. PluginConfig map[string]string // MaxSignatureAttempts is the maximum number of signature envelopes that // will be processed for verification. If set to less than or equals // to zero, an error will be returned. MaxSignatureAttempts int // UserMetadata contains key-value pairs that must be present in the // signature UserMetadata map[string]string }
VerifyOptions contains parameters for notation.Verify.
Directories
¶
Path | Synopsis |
---|---|
Package config provides the ability to load and save config.json and signingkeys.json.
|
Package config provides the ability to load and save config.json and signingkeys.json. |
Package dir implements Notation directory structure.
|
Package dir implements Notation directory structure. |
internal
|
|
semver
Package semver provides functions related to semanic version.
|
Package semver provides functions related to semanic version. |
Package log provides logging functionality to notation.
|
Package log provides logging functionality to notation. |
Package plugin provides the tooling to use the notation plugin.
|
Package plugin provides the tooling to use the notation plugin. |
proto
Package proto defines the protocol layer for communication between notation and notation external plugin.
|
Package proto defines the protocol layer for communication between notation and notation external plugin. |
Package registry provides access to signatures in a registry
|
Package registry provides access to signatures in a registry |
Package signer provides notation signing functionality.
|
Package signer provides notation signing functionality. |
Package verifier provides implementations of notation.Verifier and notation.BlobVerifier interfaces.
|
Package verifier provides implementations of notation.Verifier and notation.BlobVerifier interfaces. |
crl
Package crl provides functionalities for crl revocation check.
|
Package crl provides functionalities for crl revocation check. |
trustpolicy
Package trustpolicy provides functionalities for trust policy document and trust policy statements.
|
Package trustpolicy provides functionalities for trust policy document and trust policy statements. |
truststore
Package truststore reads certificates in a trust store
|
Package truststore reads certificates in a trust store |