owned this note
owned this note
Published
Linked with GitHub
# Sign Arbitrary Data
## Usecase / Requirements
Requirements and use case are drawn from [notation/issues/741](https://github.com/notaryproject/notation/issues/741) and [notation/discussions/767](https://github.com/notaryproject/notation/discussions/767)
1. Notation MUST support the signing of arbitrary binary data.
2. Notation MUST support the verification of arbitrary data.
i. For verification, Notation MUST provide the fine-grain control it currently offers using a trust policy and plugin model.
ii. For verification, the Notation MUST provide out of box verification once the trust store and trust policy is defined i.e. support `notation blob verify --signature ${location} ${location}`
3. Notation MAY support verification of signed arbitrary binary data that was later pushed along with signature to OCI registry.
Included 3rd usecase because it was called out in the [(issue comment)](https://github.com/notaryproject/notation/issues/741#issuecomment-1644323623).
However, it is important to note that we won't be able to support it because when dealing with an OCI artifact, Notation signs the artifact's manifest. In contrast, for arbitrary non-OCI artifacts, Notation signs the artifacts directly. This means that a signature generated for one will not be compatible (verification will fail) with the other.
## [signature-specification](https://github.com/notaryproject/specifications/blob/main/specs/)
## [Signature Payload](https://github.com/notaryproject/specifications/blob/main/specs/signature-specification.md#payload)
Currently, the signature payload is a descriptor, which is a JSON object consisting of a single key called 'targetArtifact'. Within 'targetArtifact', there are four fields:
1. `mediaType`: This REQUIRED property represents the type of data being signed or verified. This is useful in determining the nature/kind of the data.
2. `digest`: This REQUIRED property represents the hash of the data being signed or verified. Digest ensures data integrity..
3. `size`: This REQUIRED property represents the size of the data being signed or verified.`size` protects users against endless data attacks.
4. `annotations`: This OPTIONAL property is used by notation for storing user-defined metadata.
```jsonc
{
"targetArtifact": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333",
"size": 16724,
"annotations": {
"io.wabbit-networks.buildId": "123" //user-defined metadata
}
}
}
```
### 1- Continue to sign descriptor *(recommended)*
In this option, Notation will create a descriptor using the data provided by the user. The descriptor will contain the following fields:
1. `digest`: will be computed by applying a hash function to the input data.
a. digest algorithm will be derived from signing key.
3. `size`: will represent the size of the input data.
4. `mediatype` will be the media type of data being signed or verified. Notation will introduce a new optional parameter that will allow users to specify the media type. If this parameter is not provided, Notation will default to [application/octet-stream](https://www.iana.org/assignments/media-types/application/octet-stream). Similarly, during the verification, Notation will accept an optional parameter to compare the media type provided with the one stored in the signature envelope.
```shell!
$ notation blob sign --signature ${outputSigLocation} --media-type ${mediaType} ${fileLocation}
$ notation blob verify --signature ${sigLocation} --media-type ${mediaType} ${fileLocation}
```
callout: cosign uses `cosign sign-blob` for signing non-oci artifacts. Notation will introduce a set of new subcommands for blob signing usecase. Artifact types like `oci`, `blob` will become first level of sub commands and verbs like `sign`, `verify`, `inspect` will become second level sub commands. If user does not provide the first level i.e. artifact type sub command, Notation will fallback to signing OCI artifacts. This two level command hierarchy is preferred over introducing flags like `--blob` as some of the flags applicable to the `notation sign` command like `--username`, `--password` do not apply when users are signing non-OCI data.
:::spoiler other options explored
### 2- sign digest calculated from input
In the descriptor, both digest and size are critical components and essential for defense in depth. While mediaType is optional, it is beneficial to include. Annotations, on the other hand, are optional and currently being used only for storing user-defined metadata. Notation-defined metadata is stored as protected headers in JWS and COSE signature format.
In this option, Notation will directly sign digest calculated from the input data. Additionally, all other metadata, including notation-defined attributes and user-defined metadata, will be incorporated into the protected header of the JWS or COSE.
:::
## [trust-store-trust-policy](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md) for oci-artifacts
At present, notation supports trust policy, allowing users to specify trusted identities and signature verification level. Additionally, trust policy allows users to craft fine-grained policies tailored to specific repositories through the use of `registryScopes`.
Below is an example of a trust policy:
```json
{
"version": "1.0",
"trustPolicies": [
{
"name": "wabbit-networks-images", // Name of the policy.
"registryScopes": [ "*" ], // The registry artifacts to which the policy applies.
"signatureVerification": { // The level of verification - strict, permissive, audit, skip.
"level" : "audit"
},
"trustStores": ["ca:acme-rockets"], // The trust stores that contains the X.509 trusted roots.
"trustedIdentities": [ // Identities that are trusted to sign the artifact.
"x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder"
]
}
]
}
```
The `registryScopes` concept is not applicable for non-OCI artifacts (arbitrary data) as they may be stored outside of a container registry. Therefore, to facilitate the signing of non-OCI artifacts, we must assess the relevance and applicability of scopes.
Here are the options:
### 1. Rename policy selector `registryScopes` to `scopes` *(recommended)*
In this option, Notation's trust policy will enable the creation of fine-grained policies designed for specific use cases through the use of scopes. These 'scopes' will function similarly to `registryScopes`, but without the requirement of artifacts to be stored registry. Consider scopes as a user-defined policy selection string i.e. when a user is verifying a non-OCI artifact, the scope serves as a text field that allows the user to choose which trust policy to use for verification.
It's important to note that this change will be backward compatible, meaning Notation will continue to support `registryScopes` for the verification of OCI artifacts stored in a registry, and `registryScopes` would act as an alias for `scopes`. However, since the policy language is being changed, we will update the policy language version to 1.1 to indicate the changes in the language. Notation as a tool will be backward compatiable as in it will support both 1.0 and 1.1 versions of policy language. However, notation will reject policy documents mixed concepts from 1.0 and 1.1.
To eliminate the possibility of using a scope for blobs when it is actually meant for verifying oci artifacts (and vice versa), it is important to disambiguate which artifiact type a policy should be scoped to. In order to support this usecase, the values in the `scopes` filed must include a prefix about what artifacts the scope should be limited to. The prefix for OCI artifacts is `oci` and the prefix for artitrary blobs is `blob`. This is an extensible way of supporting scopes so that trust policies can support more and more types of artifacts in the future. This also allows Notation to run effective validations when trust policies are getting constructed. For example, if a user gives a free form text for `oci` scope, Notation can throw a validation error saying the given value is not an URI.
To support wildcard scopes, users of Notation can provide either `oci:*` or `blob:*`. Global wildards i.e. `*` will not be supported.
```jsonc
{
{
"name": "wabbit-networks-non-oci",
"signatureVerification": {
"level": "strict"
},
"trustStores": [ "ca:someCA-A" ],
"scopes": [ "oci:registry.acme-rockets.io/software/net-monitor" ]
},
{
"name": "wabbit-networks-non-oci2",
"signatureVerification": {
"level": "audit"
},
"trustStores": [ "ca:someCA-B" ],
"scopes": [ "oci:*" ]
},
{
"name": "globalPolicy1",
"signatureVerification": {
"level": "enforce"
},
"trustStores": [ "ca:someGlobalCC" ],
"scopes": [ "blob:my-blob-selector" ]
},
{
"name": "globalPolicy2",
"signatureVerification": {
"level": "audit"
},
"trustStores": [ "ca:someGlobalCD" ],
"scopes": [ "blob:*" ]
}
}
```
In Notation, we will introduce support for a new flag, tentatively named `--policy-scope ${scopes}`. Depending on the value provided for this flag, Notation will employ plain string matching to determine the policy for signature verification. `--policy-scope` can only be used when verifying artifacts not stored in the registry (which Notation determines by using the second level command).
```shell!
$ notation blob verify --signature ${sigLocation} --policy-scope ${non-oci} ${fileLocation}
```
*OCI layout signing uses `registryScopes` in trust-policy and `--scope` in CLI; so we recommend changing `--scope` to `--policy-scope`. Based on decisions in this doc, we will update oci-layout signing/verification commands/flags accordingly*
#### Benefits of Utilizing the 'scopes' field as a Policy Selector as compared to 'name'
1. Enablement of a default Policy with `*` as the Scope. This eliminates the necessity for users to always pass the `--policy-scope` parameter.
2. Avoiding confusion: By employing the `scopes` field as the policy selector, we maintain consistency with existing trust policy practices. Using `name` as a policy selector could potentially lead to confusion for existing customers. In the context of verifying OCI artifacts, `name` serves as a label for policies without any specific significance. However, in non-OCI scenarios, we will be using it as the policy selector.
#### 1.a Use mediatype as policy selector (not recommended)
In this option, notation ill use mediatype as policy selector i.e mediatype information stored in signature payload to select the trustpolicy.
**Sample Signature Payload:**
```jsonc
{
"targetArtifact": {
"mediaType": "application/msword",
"digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333",
"size": 16724,
"annotations": {
"io.wabbit-networks.buildId": "123" //user-defined metadata
}
}
}
```
**Sample Trust-πolicy:**
```jsonc
{
{
"name": "wabbit-networks-non-oci",
"signatureVerification": {
"level": "audit"
},
"trustStores": [ "ca:someCA-A" ],
"media-type": [ "application/msword" ]
}
}
```
Concerns with using 'mediatype' for trust policy selection:
1. The 'mediatype' is enclosed within the signature, and its content is determined by the artifact producer. As a result, the artifact producer dictates the choice of trust-policy, subsequently determining the trust-store used for signature verification. This introduces a potential vulnerability, enabling external actors (such as the artifact producer) to potentially exploit the least secure Certificate Authority (CA) within the trust policy or trust store, thereby bypassing signature verification. The detailed steps of this exploit are as follows:
1. An external actor gains unauthorized access to the artifact distribution system, such as an S3 bucket or file server.
1. An external actor identifies the weakest CA specified in the user's trust-policy and compromises the weakest CA.
2. The external actor starts siging malicious artifacts with the mediatype associated with the compromised CA in the trust-policy.
3. The signature verification succeeds for malicious artifacts.
4. Another version of this attack would be, signing an artifact with mediatype for which signature verification is marked as skip.
2. While 'mediatype' is optional by default, incorporating it into the trust policy mandates its inclusion.
:::spoiler other options explored
### 2 - Don't support policy selector i.e. no scopes
In this option, Notation's trust policy will not support a policy selector for verifying non-oci artifacts thus limiting the `trustpolicy.json` file to contain a maximum of one policy.
To support the verification of multiple trust stores and trust anchors notation can employ one of the following solutions:
#### 2.a) Support override of trust policy
To accommodate the verification of artifacts signed using different CAs, Notation CLI will support a mechanism that will allow the overriding of trust policy. This can be accomplished by allowing users to override the location of `trustpolicy.json` file using either a CLI flag or environment variable.
To facilitate the verification of artifacts signed with various Certificate Authorities (CAs), the Notation CLI will support a mechanism by which users can override the trust policies. This can be accomplished by allowing users to override the location of `trustpolicy.json` file using either a CLI flag or environment variable.
**Note:** If a policy location override is not enabled, Notation will search for the trust policy at the default (current) location. Additionally, this can also be implemented with option 1, considering it as a feature enhancement in Notation
```json
{
"name": "global-policy-for-all-other-images"
"signatureVerification": {
"level" : "audit"
},
"trustStores": ["ca:aws-signer-ts"],
}
```
```shell!
$ notation verify ${file_location} --policy ${/someDir/policy.json}
```
```shell!
$ NOTATION_POLICY=${/someDir/policy.json}
$ notation verify ${file_location}
```
#### Option 2.b - Support specifying trust policy in CLI
For non-oci artifacts don't support the concept of `trustpolicy.json` instead allow the user to provide values required for verification as CLI arguments.
**Note:** This option can also be implemented with option 1, considering it as an overall feature enhancement in Notation
```shell!
$ notation verify --trust-store ${ca:someCA-ts} --trust-identitiy ${someValue} --level ${strict | permissive | adudit}
```
###### Implications of supporting trustpolicy overrides
Pros:
1. Reduces getting started friction by eliminating the need for users to understand/configure trust-policy.
Cons:
1. Less secure when Notation adds support for system-level trust-store and trust-policy. To mitigate this, we can introduce a mechanism to disable trust policy override when the Notation is intended to run in system-level mode.
i. Currently, the user that invokes notation also controls ts and tp so the user calling notation can anyway override ts and tp.
:::
## Misc changes
### [plugin-extensibility](https://github.com/notaryproject/specifications/blob/main/specs/plugin-extensibility.md)
The notation <-> plugin interface will remain unchanged, and it will function in the same manner as it does with OCI artifacts
### Support reading input data from std-in and return signature as std-out
**Usecase-1**: Facilitate command chaining, allowing users to seamlessly pass the output of one executable as input to another.
**Usecase-2**: Enable other executables or services to call the Notation CLI for signing and verifying signatures.
```shell!
$ curl www.example.com | notation blob sign --signature - - | curl --request POST --data-binary @- www.example.com/signature
```
*Read more about using '-' for stdout and stdin at https://clig.dev/#arguments-and-flags*
## CLI Spec
### Sign
#### Successful execution
```shell!
$ notation blob sign --signature ${outputSigLocation} ${fileLocation}
# output: no output with exit code of 0 on successful execution
```
*Reason:* Ideally we would like to emit a signature on successful execution but in the case of some signature format like cose output is binary and won't be readable. [ref](https://hackmd.io/ewbJr2ZnT4a8U1ObDVXcSw?both#COSE-and-JWS-signature-std-out)
#### Failed execution
```shell!
$ notation blob sign --signature ${outputSigLocation} ${fileLocation}
# output: "Error: specific error"
```
#### All flags
```shell!
$ notation blob sign --signature ${outputSigLocation} --media-type ${mediaType} ${fileLocation}
```
1. `--signature` is a mandatory flag when `blob` subcommand is used. For notation-1.1, we will restrict the `--signature` to be used only with the `blob` command.
2. `--media-type` is an optional flag. For Notation-1.1, we will restrict it to be used only with the `blob` command.
### Verify
#### Successful execution
```shell!
$ notation blob verify --signature ${sigLocation} ${fileLocation}
# output: "Successfully verified signature for ${fileLocation}"
```
#### Failed execution
```shell!
$ notation blob verify --signature ${sigLocation} ${fileLocation}
# output: "Error: signature verification failed"
```
#### All flags
```shell!
$ notation blob verify --signature ${sigLocation} --media-type ${mediaType} --policy-scope ${non-oci} ${fileLocation}
```
1. `--signature` is a required flag when `blob` is used. For notation-1.1, we will restrict it to be used only with the `blob` command.
2. `--media-type` is an optional flag. For notation-1.1, we will restrict it to be used only with the `blob` command.
3. `--policy-scope` is an optional flag. For notation-1.1, we will restrict it to be used only with the `blob` command.
### Inspect
#### Successful execution
```shell!
$ notation blob inspect ${sigLocation}
# output:
application/vnd.cncf.notary.signature
├── signature algorithm: RSASSA-PSS-SHA-256
├── signed attributes
│ ├── content type: application/vnd.cncf.notary.payload.v1+json
│ ├── signing scheme: notary.signingAuthority.x509
│ ├── signing time: Fri Jun 23 22:04:01 2023
│ ├── expiry: Sat Jun 29 22:04:01 2024
│ └── io.cncf.notary.verificationPlugin: com.example.nv2plugin
├── unsigned attributes
│ ├── io.cncf.notary.timestampSignature: <Base64(TimeStampToken)>
│ └── io.cncf.notary.signingAgent: notation/1.0.0
├── certificates
│ ├── SHA256 fingerprint: b13a843be16b1f461f08d61c14f3eab7d87c073570da077217541a7eb31c084d
│ │ ├── issued to: wabbit-com Software
│ │ ├── issued by: wabbit-com Software Root Certificate Authority
│ │ └── expiry: Sun Jul 06 20:50:17 2025
│ ├── SHA256 fingerprint: 4b9fa61d5aed0fabbc7cb8fe2efd049da57957ed44f2b98f7863ce18effd3b89
│ │ ├── issued to: wabbit-com Software Code Signing PCA 2010
│ │ ├── issued by: wabbit-com Software Root Certificate Authority
│ │ └── expiry: Sun Jul 06 20:50:17 2025
│ └── SHA256 fingerprint: ea3939548ad0c0a86f164ab8b97858854238c797f30bddeba6cb28688f3f6536
│ ├── issued to: wabbit-com Software Root Certificate Authority
│ ├── issued by: wabbit-com Software Root Certificate Authority
│ └── expiry: Sat Jun 23 22:04:01 2035
└── signed artifact
├── media type: application/text
├── digest: sha256:b94d27b9934d3e08a52e52d7da7fac484efe37a5380ee9088f7ace2efcde9
└── size: 167244
```
* `--signature` is an required flag when verifing blob signatures.
## Appendix
### COSE and JWS signature std-out example
:::spoiler
```shell!
$ oras blob fetch $COSE_SIG --output - ҄X��8$�x*�H��cf.notary.signingSchemex+application/vnd.cncf.notary.payload.v1+jsonxio.cncf.notary.signingTime�e 4xio.cncf.notary.signingSchemeknotary.x509�!�Y\0�X0�@�s0
0[1
0 UUS1
U 0 WA10USeattle10
231007161638Z0[1networks.ios0
0 UUS1
U 0 WA10USeattle10
�0�ary10*�H��it-networks.ios0�"0
���-�_b2�[o)��.l��yz
Ъ8�_J/�!P ��X��6�wK�h٬k�=��g�Er����
?�^��]�(��*�#��@�n�g�q����D��)Ë��p��w[٘���
[��"9PLa5L��E��4����=���%�Q��]�����=ӑ9�F���������G�m���;A�˩����uɅFfQ���Ә}g
:?M��q�$�Q.����K��Yz`c�}�'0%0U��0U%
0
+0 *�H��
�ϙ��.5r�G�B��U��=��p��W1�X����
���'�_^U^�W��AŌ�C���*5p"F+*;����_j�� �#)�x���kt�:�E�����ᝇ�\S��3�n�hJ9��؇ͳ�ʉ�e�=i�ԚFHru[�Ϗ=��xS(.���}O�%��CN�m��h���^&��U�D��/$��]�����Ͼ�C@��X<���l6w8П"���Kܬ�e�/���!jt6xo.cncf.notary.signingAgentnNotation/1.0.0X�{"targetArtifact":{"mediaType":"application/vnd.docker.distribution.manifest.v2+json","digest":"sha256:0d9da41749c55ae56e46edd90a722fb1e15c97ad0248afc95b01c731b3491f9b","size":514}}YBF�^*�w@��61�� ����r
��)[!v��J R�
)å6�IC�Jx%��!7B
`�xb㜾j���n���NC�J;��T0>;�� �K��]��n�Ȏ<��
�<�B[v�7�,�vg��"}c�5�v7G�Fl�,'�"�8_�_�:�"b>��
-�P�d���N�&r�
9z
$ oras blob fetch $JWS_SIG --output -
{"payload":"eyJ0YXJnZXRBcnRpZmFjdCI6eyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC5saXN0LnYyK2pzb24iLCJkaWdlc3QiOiJzaGEyNTY6ZGEyN2I3NDAwOGJmYTQ5YTYyNWZhODVmNjZkMTJhMmY3YzE3ZGM0OTY4ZmJhZTZjOWRiNmU2N2ZkZDRmMjM4MiIsInNpemUiOjY4M319","signature":"yfM1LIWcQLuYm3lw9lvL6uRaU_nSYWruGC3kw0Uf-VytClo4UXtIXnhPI1W9tKsUVoMejJIxFYi6lOWluzO_dD_rHQNmQ_iOnBNUiziyS53WitT7OofOJpsccMYU4Aq2","header":{"x5c":["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"]},"protected":"eyJpby5jbmNmLm5vdGFyeS5leHBpcnkiOiIyMDI2LTA2LTExVDE5OjAxOjA1LjA2MVoiLCJjcml0IjpbImlvLmNuY2Yubm90YXJ5LmV4cGlyeSIsImlvLmNuY2Yubm90YXJ5LmF1dGhlbnRpY1NpZ25pbmdUaW1lIiwiaW8uY25jZi5ub3RhcnkudmVyaWZpY2F0aW9uUGx1Z2luIiwiY29tLmFtYXpvbmF3cy5zaWduZXIuc2lnbmluZ1Byb2ZpbGVWZXJzaW9uIiwiY29tLmFtYXpvbmF3cy5zaWduZXIuc2lnbmluZ0pvYiIsImlvLmNuY2Yubm90YXJ5LnNpZ25pbmdTY2hlbWUiXSwiaW8uY25jZi5ub3RhcnkuYXV0aGVudGljU2lnbmluZ1RpbWUiOiIyMDIzLTA5LTE1VDE5OjAxOjA1LjA2MVoiLCJjdHkiOiJhcHBsaWNhdGlvblwvdm5kLmNuY2Yubm90YXJ5LnBheWxvYWQudjEranNvbiIsImlvLmNuY2Yubm90YXJ5LnZlcmlmaWNhdGlvblBsdWdpbiI6ImNvbS5hbWF6b25hd3Muc2lnbmVyLm5vdGF0aW9uLnBsdWdpbiIsImNvbS5hbWF6b25hd3Muc2lnbmVyLnNpZ25pbmdQcm9maWxlVmVyc2lvbiI6ImFybjphd3M6c2lnbmVyOnVzLXdlc3QtMjo5NTE1ODQxMTMxNTc6XC9zaWduaW5nLXByb2ZpbGVzXC9FQ1JcLzJ1Q21sRm1yRXoiLCJjb20uYW1hem9uYXdzLnNpZ25lci5zaWduaW5nSm9iIjoiYXJuOmF3czpzaWduZXI6dXMtd2VzdC0yOjk1MTU4NDExMzE1NzpcL3NpZ25pbmctam9ic1wvY2UzZWYyYzgtMjc0ZC00MmMwLTljMWItNWE3MzhhMWJjZjNiIiwiYWxnIjoiRVMzODQiLCJpby5jbmNmLm5vdGFyeS5zaWduaW5nU2NoZW1lIjoibm90YXJ5Lng1MDkuc2lnbmluZ0F1dGhvcml0eSJ9"}
```
:::
### Support for signing arbitrary data and then uploading to OCI
:::warning
This section is still in the brainstorming phase and is not in scope for notation-1.1
:::
This is a workaround for 3rd requirement. Notation can provide a new subcommand that will upload the sbom per say any artifact to OCI registry and then sign it. Similarly for download and verification of artifact notation will add a new subcommand.
```shell!
$ notation attach ${IMAGE} ${fileLocation} // OR
$ notation attest ${IMAGE} ${sbom}
$ notation verify-attestation ${IMAGE} {attestConditions}
verifies and downloads the attestation
```