Documentation
¶
Overview ¶
Package notation provides signer and verifier for notation Sign and Verification.
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 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.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}}
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 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) }
Output:
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.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) }
Output:
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 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)
Output:
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.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) }
Output:
Index ¶
- func Sign(ctx context.Context, signer Signer, repo registry.Repository, ...) (ocispec.Descriptor, error)
- type ErrorNoApplicableTrustPolicy
- type ErrorPushSignatureFailed
- type ErrorSignatureRetrievalFailed
- type ErrorUserMetadataVerificationFailed
- type ErrorVerificationFailed
- type ErrorVerificationInconclusive
- type SignOptions
- type Signer
- type SignerSignOptions
- type ValidationResult
- type VerificationOutcome
- type Verifier
- type VerifierVerifyOptions
- type VerifyOptions
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Sign ¶
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.
Types ¶
type ErrorNoApplicableTrustPolicy ¶
type ErrorNoApplicableTrustPolicy struct {
Msg string
}
ErrorNoApplicableTrustPolicy is used when there is no trust policy that applies to the given artifact
func (ErrorNoApplicableTrustPolicy) Error ¶
func (e ErrorNoApplicableTrustPolicy) Error() string
type ErrorPushSignatureFailed ¶
type ErrorPushSignatureFailed struct {
Msg string
}
ErrorPushSignatureFailed is used when failed to push signature to the target registry.
func (ErrorPushSignatureFailed) Error ¶
func (e ErrorPushSignatureFailed) Error() string
type ErrorSignatureRetrievalFailed ¶
type ErrorSignatureRetrievalFailed struct {
Msg string
}
ErrorSignatureRetrievalFailed is used when notation is unable to retrieve the digital signature/s for the given artifact
func (ErrorSignatureRetrievalFailed) Error ¶
func (e ErrorSignatureRetrievalFailed) Error() string
type ErrorUserMetadataVerificationFailed ¶
type ErrorUserMetadataVerificationFailed struct {
Msg string
}
ErrorUserMetadataVerificationFailed is used when the signature does not contain the user specified metadata
func (ErrorUserMetadataVerificationFailed) Error ¶
func (e ErrorUserMetadataVerificationFailed) Error() string
type ErrorVerificationFailed ¶
type ErrorVerificationFailed struct {
Msg string
}
ErrorVerificationFailed is used when it is determined that the digital signature/s is not valid for the given artifact
func (ErrorVerificationFailed) Error ¶
func (e ErrorVerificationFailed) Error() string
type ErrorVerificationInconclusive ¶
type ErrorVerificationInconclusive struct {
Msg string
}
ErrorVerificationInconclusive is used when signature verification fails due to a runtime error (e.g. a network error)
func (ErrorVerificationInconclusive) Error ¶
func (e ErrorVerificationInconclusive) Error() string
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 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.Sign.
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 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 return 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 (*VerificationOutcome) UserMetadata ¶
func (outcome *VerificationOutcome) UserMetadata() (map[string]string, error)
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 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 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 an implementation of notation.Verifier interface
|
Package verifier provides an implementation of notation.Verifier interface |
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 |