owned this note
owned this note
Published
Linked with GitHub
# Notary V2 - Signature Format
###### tags: `notary`
[Notary Issue #86](https://github.com/notaryproject/notaryproject/issues/86)
This document defines the requirements of the signature format and discusses the candidates for Notary V2.
## Definition
A complete signature $\Sigma = (m, \mu, \hat\mu, \sigma) \gets \mathbf{Sign}(sk, m)$ is a tuple of
- Signed payload $m$.
- Signed signature metadata $\mu$.
- Unsigned signature metadata $\hat\mu$.
- Cryptographic signature $\sigma$.
where $sk$ stands for signing key.
![A complete signature in OCI registry](https://i.imgur.com/ASv4A6o.png)
A signature envelope $\varepsilon_n = \{ m, (\mu_0, \hat\mu_0, \sigma_0), \dots, (\mu_{n-1}, \hat\mu_{n-1}, \sigma_{n-1}) \}$ is a compact form of $n$ signatures signing the same payload $m$. It can be expanded to $\Sigma_i = (m, \mu_i, \hat\mu_i, \sigma_i),\ \forall i \in \mathbb{Z}_n$.
A complete signature $\Sigma$ can be viewed as a signature envelope $\varepsilon_1$.
## Requirements
Since payload is about the metadata of the artifact manifest to be signed and it is not specific to any signature scheme, the payload requirements are discussed separately.
### Payload
- The payload MUST be a byte sequence.
- The payload MUST contain a [descriptor](https://github.com/opencontainers/image-spec/blob/master/descriptor.md#properties) of the target manifest.
- A descriptor MUST contain `mediaType`, `digest`, `size` fields.
- A descriptor MAY contain a `annotations` field.
- A descriptor MAY contain the `artifactType` field for artifact manifests, or the `config.mediaType` for `oci.image` based manifests.
- Artifact identity MAY be indicated in the payload.
- When indicated, the verifier SHOULD verify the origin against the signer.
### Signature
- A signature MUST be stored or transferred in a signature envelope.
- A signature envelope SHOULD be encoded in a single file.
- A signature envelope MUST contain one and only one complete signature.
- Multiple signatures for a subject manifest MUST be represented as seperate signature manifest and signature envelope (blob) pairs.
- The signing algorithm MAY be indicated in the signed signature metadata.
- There is a concern on the signing algorithm not matching the verification key.
- See [CS-DRNT15-1 Section 3.3](https://github.com/theupdateframework/notary/blob/master/docs/resources/ncc_docker_notary_audit_2015_07_31.pdf).
- Similar vulnerability is introduced in [A cross-protocol attack on the TLS protocol](https://doi.org/10.1145/2382196.2382206) by Mavrogiannopoulos et al.
- Detailed discussions can be found at [secure-systems-lab/dsse#35](https://github.com/secure-systems-lab/dsse/issues/35).
- The signing timestamp MAY be in the signed signature metadata.
- The signature expiry time MAY be in the signed signature metadata.
- The signed signature metadata MAY contain information that allows verifiers to determine if the artifact is revoked.
- The contents of this attribute are pending the outcome of artifact level revocation design.
- If the signature is timestamped by a TSA, the timestamp and the corresponding signatures MUST be stored in the unsigned signature metadata.
- If the signature was produced by a X.509 certificate, the signature MUST contain the complete certificate chain of the signing certificate as an unsigned attribute.
- The thumbprint of the signing certificate MAY be indicated in the unsigned signature metadata.
### Signature Format
- A signature format MUST be able to store the payload.
- A signature format MUST be able to store the cryptographic signature.
- A signature format MUST be able to store unsigned signature metadata.
- _This requirement is essential for TSA._ To time stamp a signature, the original signature must be generated first and then sent to a TSA for time stamping. Once obtained the timestamp signature, it will be attached to the original signature.
- A signature format MAY be able to store signed signature metadata.
- In case of a signature format candidate being unable to store signed signature metadata, the signed signature metadata can be combined with the payload before signing. Since the payload contains the signature specific metadata, the signature format loses the ability to store multiple signatures.
- *Signature format MUST support referencing and inlining of different identity types such as key(s) and certificate(s).*
- *Signature format SHOULD be easy to implement using existing Go libraries(Docker CLIs are developed in Go).*
- *Signature format MAY be able to store multiple signatures generated using same or different cryptographicmaterials(identity types and signing algoritms).*
- *Signature format MAY support counter signature.*
## Existing Formats
### JWT variant
Notary v2 `version <= prototype-2` defines a [JWT-variant signature format](https://github.com/notaryproject/nv2/tree/prototype-2/docs/signature).
Particularly, this JWT-variant is serialized in JWS Compact Serialization as defined by [RFC7515 Section 7.1](https://datatracker.ietf.org/doc/html/rfc7515#section-7.1).
Pros:
- Commonly used.
- Libraries can be found for many languages.
- More flexible.
Cons:
- Consumes the header before authenticating.
- Verifiers can be tricked into MAC algorithms instead of asymmetric key signing.
- Example: [RSA or HMAC?](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)
- This variant may not be compatible with all existing libraries.
- Current implementation relies on [docker/libtrust](https://github.com/docker/libtrust), which is archived.
- Does not support unsigned signature metadata.
- Cannot be extended to support TSA.
Example:
```
eyJ0eXAiOiJ4NTA5IiwiYWxnIjoiUlMyNTYiLCJ4NWMiOlsiTUlJRHN6Q0NBcHVnQXdJQkFnSVVMMWFuRVUveUp5NjdWSlRiSGtOWDBiQk5BbkV3RFFZSktvWklodmNOQVFFTEJRQXdhVEVkTUJzR0ExVUVBd3dVY21WbmFYTjBjbmt1WlhoaGJYQnNaUzVqYjIweEZEQVNCZ05WQkFvTUMyVjRZVzF3YkdVZ2FXNWpNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0F3S1YyRnphR2x1WjNSdmJqRVFNQTRHQTFVRUJ3d0hVMlZoZEhSc1pUQWVGdzB5TURBM01qY3hORFF6TkRaYUZ3MHlNVEEzTWpjeE5EUXpORFphTUdreEhUQWJCZ05WQkFNTUZISmxaMmx6ZEhKNUxtVjRZVzF3YkdVdVkyOXRNUlF3RWdZRFZRUUtEQXRsZUdGdGNHeGxJR2x1WXpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlZCQWNNQjFObFlYUjBiR1V3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGtLd0FjVjQ0cHNqTjhubm8xZVozenYxWktVaEpBb3h3Qk9JR2ZJeEllK2lIdHBYTHZGRlZ3azVKYnh1K1BraWcyTjRCM0lscmovVnJ5aTBoeHA0bWFnMDJNNzMzYlhMUkVOU09GT05Sa3NscE84ekhVTjVwWWRuaFRTd1lUTGFwMSsxYmdjRlN1VVhMV2llcVpCNnFjN2tpdjNiajNTUGFmNDIrczQ4VjQ5dC9PcFh4THRnaVdMOVhrdURUWmN0cEpKQTR2SEhrNk91MGJjZzdpR20rTDF4d0lmYjhNbDRvV3ZUMFNGMzVmZ1cwOGJiTFhaMnYxWENMUnNyV1VnYnE0VStLeHRFcEczWElZY1loS3gxcklyVWhmRUprdUh6Z1BnbE0xMWdHNVcrQ3lmZyt3Zk9KaWc1cTZheElLV3pJZjZDOG04bG15NmJNK041RXNEOVN2QWdNQkFBR2pVekJSTUIwR0ExVWREZ1FXQkJUZjFoTTYvaWJHRit1L1NWQUs4OEZVTWp6Um9UQWZCZ05WSFNNRUdEQVdnQlRmMWhNNi9pYkdGK3UvU1ZBSzg4RlVNanpSb1RBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCZ3ZWYXU1KzJ3QXVDc21PeXlHMjhoMXp5QzRJUG1NbXBSWlRET3AvcExkd1hlSGpKcjhrRUMzbDkycUpFdmMrV0Fib0oxUm91Y0h5Y1VlN1JXaDJDNlpGL1dQQ0JMeVdHd25seXFHeVJNOS9qODZVSjFPZ2l1Wmw3a2w5enh3V29heFBCQ21IYTBSSG93ZFFCN0FWbHBxZzFjN0ZoS2poVUNCbUdUNFZlOHRWMGhkWnRyWm9RVis2eEhQYlVkMzdLVjFCMUJtZm8zbzRla29KS2hVdTk5RW8wM09wRTNKTHRNMTNBMUh4QUJFdVFHSFRJMHR5Y0RCQmRSbjNiMDNIb0loVTBWbnFqdnBWMUtQdnNyZ1lpLzBWU3RMTmV6WlBnR2UwZkczWGd5OHlla2RCOU5NVW4relpMQVRJNCt6OGo0UUg1V2o1WlBhVWt5b0FEMm9VSk8iXX0.eyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiZGlnZXN0Ijoic2hhMjU2OmM0NTE2YjhhMzExZTg1ZjFmMmE2MDU3M2FiZjRjNmI3NDBjYTNhZGU0MTI3ZTI5YjA1NjE2ODQ4ZGU0ODdkMzQiLCJzaXplIjo1MjgsInJlZmVyZW5jZXMiOlsicmVnaXN0cnkuZXhhbXBsZS5jb20vZXhhbXBsZTpsYXRlc3QiLCJyZWdpc3RyeS5leGFtcGxlLmNvbS9leGFtcGxlOnYxLjAiXSwiZXhwIjoxNjI4NTg3MTE5LCJpYXQiOjE1OTcwNTExMTksIm5iZiI6MTU5NzA1MTExOX0.MtQBOL2FERM2fMSikruHOMQdHuEXAE1wf6J6TfDY2W_7PfQQllBKbJJE0HqJ5ENAbuqNYHNZeIeKUCYFrNx2XgtrKuTe7WCa1ZZKDtp5bmANp484ekdl6lW23YB8r_SRtseJuibqjI3HuiMyELj9uYV1CdRYaD2BIZ_qxraYH1fMpjDWjehU4RYLI37hsSuDQ90o09BwaNfzbQXYPsGmkSUSmej7rOFPDnuwhNy4WcUed3kRKYEW8eIjO9OUBGQq3PWvhDjxZi3QF4QFDoiKBOXL70AjaiVIveQRkJI9-xHZSYwje9OFEMioeNWB5ceZR-r4L7VzDcU-Fxqjxn79Fw
```
If parsed,
```json
{
"typ": "x509",
"alg": "RS256",
"x5c": [
"MIIDszCCApugAwIBAgIUL1anEU/yJy67VJTbHkNX0bBNAnEwDQYJKoZIhvcNAQELBQAwaTEdMBsGA1UEAwwUcmVnaXN0cnkuZXhhbXBsZS5jb20xFDASBgNVBAoMC2V4YW1wbGUgaW5jMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTAeFw0yMDA3MjcxNDQzNDZaFw0yMTA3MjcxNDQzNDZaMGkxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUuY29tMRQwEgYDVQQKDAtleGFtcGxlIGluYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkKwAcV44psjN8nno1eZ3zv1ZKUhJAoxwBOIGfIxIe+iHtpXLvFFVwk5Jbxu+Pkig2N4B3Ilrj/Vryi0hxp4mag02M733bXLRENSOFONRkslpO8zHUN5pYdnhTSwYTLap1+1bgcFSuUXLWieqZB6qc7kiv3bj3SPaf42+s48V49t/OpXxLtgiWL9XkuDTZctpJJA4vHHk6Ou0bcg7iGm+L1xwIfb8Ml4oWvT0SF35fgW08bbLXZ2v1XCLRsrWUgbq4U+KxtEpG3XIYcYhKx1rIrUhfEJkuHzgPglM11gG5W+Cyfg+wfOJig5q6axIKWzIf6C8m8lmy6bM+N5EsD9SvAgMBAAGjUzBRMB0GA1UdDgQWBBTf1hM6/ibGF+u/SVAK88FUMjzRoTAfBgNVHSMEGDAWgBTf1hM6/ibGF+u/SVAK88FUMjzRoTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBgvVau5+2wAuCsmOyyG28h1zyC4IPmMmpRZTDOp/pLdwXeHjJr8kEC3l92qJEvc+WAboJ1RoucHycUe7RWh2C6ZF/WPCBLyWGwnlyqGyRM9/j86UJ1OgiuZl7kl9zxwWoaxPBCmHa0RHowdQB7AVlpqg1c7FhKjhUCBmGT4Ve8tV0hdZtrZoQV+6xHPbUd37KV1B1Bmfo3o4ekoJKhUu99Eo03OpE3JLtM13A1HxABEuQGHTI0tycDBBdRn3b03HoIhU0VnqjvpV1KPvsrgYi/0VStLNezZPgGe0fG3Xgy8yekdB9NMUn+zZLATI4+z8j4QH5Wj5ZPaUkyoAD2oUJO"
]
}.{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:c4516b8a311e85f1f2a60573abf4c6b740ca3ade4127e29b05616848de487d34",
"size": 528,
"references": [
"registry.example.com/example:latest",
"registry.example.com/example:v1.0"
],
"exp": 1628587119,
"iat": 1597051119,
"nbf": 1597051119
}.[Signature]
```
### JWS JSON Serialization
General JWS JSON serialization syntax is defined in [RFC7515 Section 7.2.1](https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.1).
Pros:
- Well defined in [RFC7515](https://datatracker.ietf.org/doc/html/rfc7515), [RFC7518](https://www.rfc-editor.org/rfc/rfc7518), [RFC7519](https://datatracker.ietf.org/doc/html/rfc7519)
Cons:
- [Security concerns](https://github.com/secure-systems-lab/dsse/blob/master/background.md#motivation) on payload type.
- Resolved by signing [cty](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.10) header.
Here is an example:
Payload:
```json
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 525,
"digest": "sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792",
"annotations": {
"notary.v2.identity": "registry.wabbit.net/hello-world:1.0"
}
}
```
Signed signature metadata:
```json
{
"alg": "RS256",
"arl": "http://registry.wabbit.net/arl",
"exp": "2021-09-20T16:02:40.3375379Z",
"iat": "2021-06-22T16:02:40.3375379Z"
}
```
Complete JWS JSON Serialization:
```json
{
"payload": "ewogICAgIm1lZGlhVHlwZSI6ICJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwKICAgICJzaXplIjogNTI1LAogICAgImRpZ2VzdCI6ICJzaGEyNTY6MWIyNjgyNmY2MDI5NDY4NjBjMjc5ZmNlNjU4ZjMxMDUwY2ZmMmM1OTY1ODNhZjIzN2Q5NzFmNDYyOWI1Nzc5MiIsCiAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgIm5vdGFyeS52Mi5pZGVudGl0eSI6ICJyZWdpc3RyeS53YWJiaXQubmV0L2hlbGxvLXdvcmxkOjEuMCIKICAgIH0KfQ",
"signatures": [
{
"protected": "ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAiYXJsIjogImh0dHA6Ly9yZWdpc3RyeS53YWJiaXQubmV0L2FybCIsCiAgICAiZXhwIjogIjIwMjEtMDktMjBUMTY6MDI6NDAuMzM3NTM3OVoiLAogICAgImlhdCI6ICIyMDIxLTA2LTIyVDE2OjAyOjQwLjMzNzUzNzlaIgp9Cg",
"header": {
"kid": "906ade40b96cff95e5b60f7e96f2cda7979c8ad5",
"timestamp": "TimeStampToken/in/base64"
},
"signature": "r5ANOfLzS30CFId49egGiIQWcC-G_tX5dhsswigOUAGq1L2MIfuvV2xn4u8M33CJIbOM2e3doJSwdD6mI51y6A"
}
]
}
```
If a JWS contains only one signature as above, the JWS can be flattened as
```json
{
"payload": "ewogICAgIm1lZGlhVHlwZSI6ICJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwKICAgICJzaXplIjogNTI1LAogICAgImRpZ2VzdCI6ICJzaGEyNTY6MWIyNjgyNmY2MDI5NDY4NjBjMjc5ZmNlNjU4ZjMxMDUwY2ZmMmM1OTY1ODNhZjIzN2Q5NzFmNDYyOWI1Nzc5MiIsCiAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgIm5vdGFyeS52Mi5pZGVudGl0eSI6ICJyZWdpc3RyeS53YWJiaXQubmV0L2hlbGxvLXdvcmxkOjEuMCIKICAgIH0KfQ",
"protected": "ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAiYXJsIjogImh0dHA6Ly9yZWdpc3RyeS53YWJiaXQubmV0L2FybCIsCiAgICAiZXhwIjogIjIwMjEtMDktMjBUMTY6MDI6NDAuMzM3NTM3OVoiLAogICAgImlhdCI6ICIyMDIxLTA2LTIyVDE2OjAyOjQwLjMzNzUzNzlaIgp9Cg",
"header": {
"kid": "906ade40b96cff95e5b60f7e96f2cda7979c8ad5",
"timestamp": "TimeStampToken/in/base64"
},
"signature": "r5ANOfLzS30CFId49egGiIQWcC-G_tX5dhsswigOUAGq1L2MIfuvV2xn4u8M33CJIbOM2e3doJSwdD6mI51y6A"
}
```
### Dead Simple Signature Envelope (DSSE)
in-toto enhancement (ITE-5) introduces a [SSL signing spec](https://github.com/secure-systems-lab/signing-spec). This spec is inspired by [PASETO](https://github.com/paragonie/paseto), which is too opinionated. Later, this spec is evolved to [Dead Simple Signature Envelope (DSSE)](https://github.com/secure-systems-lab/dsse) with its [PAE()](https://github.com/secure-systems-lab/dsse/blob/master/protocol.md#signature-definition) function updated.
Pros:
- Simple.
- Security decisions only depends on the authenticated fields.
Cons:
- Less common.
- Need to find the suitable algorithm according to the known keys by brute force
Example:
```json
{
"payload": "aGVsbG8gd29ybGQ=",
"payloadType": "http://example.com/HelloWorld",
"signatures": [
{
"keyid": "key id is optional",
"sig": "y7BK8Mm8Mr4gxk4+G9X3BD1iBc/vVVuJuV4ubmsEK4m/8MhQOOS26ejx+weIjyAx8VjYoZRPpoXSNjHEzdE7nQ=="
}
]
}
```
### Red Hat's Simple Signing
Red Hat's [simple signing](https://www.redhat.com/en/blog/container-image-signing) format is intended for payloads. The payload format is adapted by `atomic` and later by [cosign](https://github.com/sigstore/cosign).
```json
{
"critical": {
"identity": {
"docker-reference": "testing/manifest"
},
"image": {
"Docker-manifest-digest": "sha256:20be...fe55"
},
"type": "atomic container signature"
},
"optional": {
"creator": "atomic",
"timestamp": 1458239713
}
}
```
It is a payload format not a signature format.
### PKCS #7: Cryptographic Message Syntax (CMS)
PKCS #7: CMS is defined in [RFC2315](https://datatracker.ietf.org/doc/html/rfc2315) and updated by [RFC5652](https://datatracker.ietf.org/doc/html/rfc5652). The CMS is widely used for general digital signatures. For instances, [RFC8551](https://datatracker.ietf.org/doc/html/rfc8551), [NuGet.org](https://devblogs.microsoft.com/nuget/introducing-repository-signatures/).
The signature is stored in asn.1 DER binary format and optionally wrapped in PEM blocks.
*Go Library: https://pkg.go.dev/go.mozilla.org/pkcs7*
Pros:
- Mature standard
- Build-in signature attribute support
- Build-in TSA support
- Build-in CRL support
Cons:
- Lack of stable Go library
- Only supports certificates
- Many implementation only support X.509 certificates such as .net.
## Recommendation
It is recommended to reuse existing signature format according the requirements. If there is no suitable candidate, extend the existing signature format for minimum viable product. If non of above meet the requirements, we may consider to design a new signature format.
### JWS JSON Serialization
JWS JSON serialization meets our requirements.
Golang implementation is possible by combining
- [github.com/golang-jwt/jwt](https://github.com/golang-jwt/jwt) for signing / verifying JWT tokens.
- [github.com/shizhMSFT/go-jwsutil](https://github.com/shizhMSFT/go-jwsutil) for JWS compact / JSON serialization conversion.
- [github.com/shizhMSFT/go-timestamp](https://github.com/shizhMSFT/go-timestamp) for timestamp request.
- [github.com/cloudflare/cfssl/crypto/pkcs7](https://github.com/cloudflare/cfssl/blob/master/crypto/pkcs7/pkcs7.go) for timestamp verification.
- Need ASN.1 BER to DER conversion.
### Example by extending DSSE
The format is proposed by extending DSSE.
Payload:
```json
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 525,
"digest": "sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792",
"annotations": {
"notary.v2.identity": "registry.wabbit.net/hello-world:1.0"
}
}
```
Signed signature metadata:
```json
{
"alg": "RS256",
"arl": "http://registry.wabbit.net/arl",
"exp": "2021-09-20T16:02:40.3375379Z",
"iat": "2021-06-22T16:02:40.3375379Z"
}
```
Signature envelope:
```json
{
"payload": "ewogICAgIm1lZGlhVHlwZSI6ICJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwKICAgICJzaXplIjogNTI1LAogICAgImRpZ2VzdCI6ICJzaGEyNTY6MWIyNjgyNmY2MDI5NDY4NjBjMjc5ZmNlNjU4ZjMxMDUwY2ZmMmM1OTY1ODNhZjIzN2Q5NzFmNDYyOWI1Nzc5MiIsCiAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgIm5vdGFyeS52Mi5pZGVudGl0eSI6ICJyZWdpc3RyeS53YWJiaXQubmV0L2hlbGxvLXdvcmxkOjEuMCIKICAgIH0KfQ==",
"payloadType": "application/vnd.cncf.notary.v2.descriptor",
"signatures": [
{
"keyid": "906ade40b96cff95e5b60f7e96f2cda7979c8ad5",
"metadata": "ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAiYXJsIjogImh0dHA6Ly9yZWdpc3RyeS53YWJiaXQubmV0L2FybCIsCiAgICAiZXhwIjogIjIwMjEtMDktMjBUMTY6MDI6NDAuMzM3NTM3OVoiLAogICAgImlhdCI6ICIyMDIxLTA2LTIyVDE2OjAyOjQwLjMzNzUzNzlaIgp9Cg==",
"timestamp": "TimeStampToken/in/base64",
"sig": "pi6YujSNkb4X1h81++AQpchnCEz9gtVXGICq/VG+4B1b8BemrVN18jRymesq9DEATHvIBJzvIK2OaLxKlZufdg=="
}
]
}
```
-----
### [PB]Example using JWS JSON Serialization
The format is proposed using JWS JSON Serialization.
**Payload:**
```json
{
"notary.v2": {
"subjectManifest": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333",
"size": 16724,
"annotations": {
"org.acme-rockets.importDate": "2021-04-23T18:25:43.511Z"
}
},
"signedAttrs": {
"reserved": {
"arl": "http://registry.wabbit.net/arl",
"identity": "acme-rockets.io/net-monitor:v1"
},
"custom" : {
"buildId": "0001",
"imageScanned": "true"
}
}
},
"iat": "2021-06-22T16:02:40.3375379Z",
"exp": "2021-09-20T16:02:40.3375379Z"
}
```
Payload contain the subject manifest and other attributes that has to be integrity protected.
* `notary.v2`: Top level node and private claim, encapsulating the notary v2 data.
* In order to leverage JWS claims functionality provided by libraries we have defined `iat`, `exp` as top level nodes.
* `subjectManifest`: The image manifest that needs to be integrity protected.
* `signedAttrs`: The additional metadata that needs to be signed.
* `reserved`: The signed attributes reserved for notary v2 use such as issuedAt(iat), expiration Time(exp), artifact revocation list(arl), etc.
* `custom`: The user defined signed attributes such as buildId, imageScanned, etc.
* To start with we will only support iat, exp and notary.v2 claim. PB[add required and optional claims]
**ProtectedHeader:**
```json
{
"alg": "RS256",
"cty": "application/<TBD>"
}
```
* JWS needs alogrithm(alg) to be present in header so we have added it as protected header.
* `cty`: Content type used to declare the media type of the secured content(the payload)
**SignatureEnvelope:**
```json
{
"payload": "<Base64Url(Payload)>",
"protected": "<Base64Url(ProtectedHeader)>"
"header": {
"timestamp": "<Base64Url(TimeStampToken)>",
"kid": "906ade40b96cff95e5b60f7e96f2cda7979c8ad5",
"x5c": ["<Base64(DER(leafCert))>", "<Base64(DER(intermediateCACert))>", "<Base64(DER(rootCert))>"]
},
"signature": "Base64Url( sign( ASCII( <Base64Url(Payload)>.<Base64Url(ProtectedHeader)> )))"
}
```
* `protected`: Base64Url encoded JSON object that contains the header parameters that are integrity
protected by the JWS Signature digital signature
* `header`: JOSE Header containing the parameters describing the cryptographic
operations and parameters employed. header is not integrety protected by signature. To start with we will only support reserved set of headers. TODO: Fail the signature if contains extra header?
* `timestamp`: Base64Url encoded [timestamp token](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2) generated by TSA.
* `kid` Hint indicating which key was used to generate the signature.
* `x5c` contains the X.509 public key certificate or certificate chain corresponding to the key used to used to generate the signature. If signature was generated by x509 certificate signature envelop must contain x5c
* In case of `x5c` the leaf certificate's signing algorithm(with some additional conventions [TODO: add convention]) will be used for signature and this algorithm will be value of `alg` header. The verifier will make sure that the value of `alg` is same as that of leaf certificate's signing algorithm.
### [PB] Example using DSSE
The format is proposed using extended version of DSSE.
**Payload:**
```json
{
"subjectManifest": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333",
"size": 16724,
"annotations": {
"org.acme-rockets.importDate": "2021-04-23T18:25:43.511Z"
}
},
"signedAttrs": {
"reserved": {
"iat": "2021-06-22T16:02:40.3375379Z",
"exp": "2021-09-20T16:02:40.3375379Z",
"arl": "http://registry.wabbit.net/arl",
"identity": "acme-rockets.io/net-monitor:v1"
},
"custom" : {
"BuildId": "0001",
"imageScanned": "true"
}
}
}
```
**SignatureEnvelope:**
```json
{
"payload": "<Base64(Payload)>",
"payloadType": "application/<TBD>",
"signatures": [
{
"keyid": "906ade40b96cff95e5b60f7e96f2cda7979c8ad5",
"x5c": ["<Base64(DER(leafCert))>", "<Base64(DER(intermediateCACert))>", "<Base64(DER(rootCert))>"],
"timestamp": "<Base64(TimeStampToken)>",
"sig": "Base64( sign( <Base64(Payload)> ))"
}
]
}
```
In SignatureEnvelope's `signatures` node user can either specify keyid or x5c. Currently DSSE doesn't support timestamp and x5c fields.
### Open Questions
1. In Payload do we need `subjectManifest#annotations`? As we have already defined `signedAttrs#custom` node for user specific metadata?
2. Should signature varification fail if signature envelop contains unsupported fields?
## Prototype scope [Draft]
- Prototype
- Use defined payload format
- Verify including
- Cert chain validation
- Exclude revocation check
- TSA signature
- Signature expiry
- ARL field (placeholder)
- Exclude ARL check
- Custom signed attributes (wrapped payload)
- Types of keys (different x5c)
- RSA
- ECDSA
- EdDSA?
## References
- [Notary Security Topics](https://hackmd.io/9mc_kvXoRc2GmjOnz0_eYA?view)
- [Notary V2 - Rescinding Signatures](https://hackmd.io/2rc07WwHTdmPjpgoMbvYfA?view)
- [Notary V2 - More Signature Format Examples](https://hackmd.io/0GKGd0-1QQirbe1yty5vPg?view)
- [Signature Samples from Prototypes](https://hackmd.io/V7-71xB_R5-k8UrdNdhlBg?view)