Pritesh Bandi
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 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 ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully