<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE rfc SYSTEM "rfc2629-xhtml.ent">

<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     submissionType="independent"
     category="info"
     tocDepth="3"
     docName="draft-jordan-jws-ct-07"
     ipr="trust200902"
     obsoletes=""
     updates=""
     xml:lang="en"
     tocInclude="true"
     symRefs="true"
     sortRefs="true"
     version="3">
    <front>
        <title abbrev="JWS/CT">
            JWS Clear Text JSON Signature Option (JWS/CT)
        </title>
        <author fullname="Bret Jordan" initials="B." surname="Jordan" role="editor">
            <organization>Broadcom</organization>
            <address>
                <postal>
                    <street>1320 Ridder Park Drive</street>
                    <region>CA</region>
                    <code>95131</code>
                    <city>San Jose</city>
                    <country>United States of America</country>
                </postal>
                <email>bret.jordan@broadcom.com</email>
            </address>
        </author>
        <author fullname="Samuel Erdtman" initials="S." surname="Erdtman">
            <organization>Spotify AB</organization>
            <address>
                <postal>
                    <street>Birger Jarlsgatan 61, 4tr</street>
                    <code>113 56</code>
                    <city>Stockholm</city>
                    <country>Sweden</country>
                </postal>
                <email>erdtman@spotify.com</email>
            </address>
        </author>
        <author fullname="Anders Rundgren" initials="A." surname="Rundgren">
            <organization>Independent</organization>
            <address>
                <postal>
                    <city>Montpellier</city>
                    <country>France</country>
                </postal>
                <email>anders.rundgren.net@gmail.com</email>
                <uri>https://www.linkedin.com/in/andersrundgren/</uri>
            </address>
        </author>
        <date year="2021"/>
        <area>Security</area>
        <workgroup/>
        <keyword>JSON</keyword>
        <keyword>Signatures</keyword>
        <keyword>Cryptography</keyword>
        <keyword>Canonicalization</keyword>

        <abstract>
            <t>
                This document describes a method for extending the scope of the
                JSON Web Signature (JWS) specification, called JWS/CT (JWS "Clear Text").
                By combining the detached mode of JWS with the
                JSON Canonicalization Scheme (JCS), JWS/CT enables
                JSON objects to remain in the JSON format after being signed.
                In addition to supporting a consistent data format, this
                arrangement also simplifies documentation, debugging, and logging.
                The ability to embed signed JSON objects in other JSON objects,
                makes the use of counter-signatures straightforward.
            </t>
            <t>
                This informational specification has been produced outside the IETF,
                is not an IETF standard, and does not have IETF consensus.  The
                intended audiences of this document are JSON tool vendors as well as
                designers of JSON-based cryptographic solutions.
            </t>
        </abstract>
    </front>
    <middle>
        <section anchor="Introduction" numbered="true" toc="default">
            <name>Introduction</name>
            <t>
                This specification introduces a method for augmenting data expressed in the
                JSON <xref target="RFC8259" format="default"/> notation,
                with enveloped signatures, similar to the scheme used in
                XML&nbsp;Signature <xref target="XMLDSIG" format="default"/>.
                For interoperability reasons this specification constrains JSON objects
                to the I-JSON <xref target="RFC7493" format="default"/> subset.
            </t>
            <t>
                To avoid "reinventing the wheel", this specification leverages
                JSON Web Signature (JWS) <xref target="RFC7515" format="default"/>.
            </t>
            <t>
                By building on the detached mode of JWS
                in combination with the JSON Canonicalizion Scheme (JCS)
                <xref target="RFC8785" format="default"/>,
                JSON objects to be signed can be kept in the JSON format.
                This arrangement is here referred to as JWS/CT, where CT stands for
                "Clear&nbsp;Text" signing.
            </t>
            <t>
                The primary motivations for keeping signed JSON objects in the JSON format
                include simplified documentation, debugging, and logging,
                as well as for maintaining a consistent message structure.
            </t>
            <t>
                Another target is HTTP-based signature schemes that currently
                utilize HTTP header values for holding detached signatures.
                By using the method described herein,
                signed JSON-formatted HTTP requests and responses
                may be self-contained and thus be serializable.
                The latter facilitates such data to be
            </t>
            <ul spacing="compact">
                <li>stored in databases</li>
                <li>passed through intermediaries</li>
                <li>embedded in other JSON objects</li>
                <li>counter-signed</li>
            </ul>
            <t>
                without losing the ability to (at any time) verify signatures.
            </t>
            <t>
                <xref target="jws-ct.applications" format="default"/> outlines different
                ways to handle multiple signatures including counter-signing using JWS/CT.
            </t>
            <t>
                The intended audiences of this document are JSON tool vendors as
                well as designers of JSON-based cryptographic solutions.
            </t>
        </section>
        <section anchor="Terminology" numbered="true" toc="default">
            <name>Terminology</name>
            <t>
                Note that this document is not on the IETF standards track. However, a
                conformant implementation is supposed to adhere to the specified behavior for
                security and interoperability reasons.  This text uses BCP 14 to
                describe that necessary behavior.
            </t>
            <t>
                The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
                "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>
                    SHALL
                    NOT
                </bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
                "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
                "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are
                to be interpreted as described in BCP&nbsp;14 <xref target="RFC2119"/>
                <xref target="RFC8174"/> when, and only when, they appear in all capitals,
                as shown here.
            </t>
        </section>

        <section anchor="Operation" numbered="true" toc="default">
            <name>Detailed Operation</name>
            <t>
                This section describes the details related to signing
                and validating signatures based on this specification.
            </t>
            <t>
                The following characteristics are crucial to know for
                prospective JWS/CT implementers and users:
            </t>
            <ul>
                <li>
                    With the exception of the reliance on the detached mode described in
                    Appendix F of JWS <xref target="RFC7515" format="default"/>,
                    JWS/CT does not alter the JWS signature creation process, validation process,
                    or format. This means that the contents of JWS headers as well as things
                    related to signature algorithms and cryptographic keys are out
                    of scope for this specification.
                    A slightly enhanced processing option is outlined in
                    <xref target="alt.mode" format="default"/>.
                </li>
                <li>
                    JWS/CT depends exclusively on the JWS Compact Serialization mode.
                </li>
                <li>
                    JSON data to be signed MUST be supplied as JSON objects.  That is,
                    direct signing of JSON arrays or JSON primitives is out of scope for this specification.
                </li>
                <li>
                    JCS <xref target="RFC8785" format="default"/>
                    constrains JSON objects to the I-JSON
                    <xref target="RFC7493" format="default"/> subset.
                </li>
            </ul>
            <t>
                The signature creation and signature validation sections
                (<xref target="signing" format="default"/> and 
                <xref target="validation" format="default"/> respectively),
                feature examples using the <tt>HS256</tt> JOSE algorithm
                <xref target="RFC7518" format="default"/>
                with a 256-bit key having the following value,
                here expressed as hexadecimal bytes:
            </t>
            <sourcecode type="test-vectors">
7f dd 85 1a 3b 9d 2d af c5 f0 d0 00 30 e2 2b 93
43 90 0c d4 2e de 49 48 56 8a 4a 2e e6 55 29 1a
            </sourcecode>
            <section anchor="signing" numbered="true" toc="default">
                <name>Signature Creation</name>
                <t>
                    The following sub-sections describe how JSON objects can be signed
                    according to the JWS/CT specification.
                </t>
                <section anchor="signing.data.creation" numbered="true" toc="default">
                    <name>Create the JSON Object to be Signed</name>
                    <t>
                        Create or parse the JSON object to be signed.
                    </t>
                    <t>
                        The following example object is used to illustrate the operations in
                        the sections that follow:
                    </t>
                    <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true]
}
                    </sourcecode>
                </section>
                <section anchor="signing.canonicalize" numbered="true" toc="default">
                    <name>Canonicalize the JSON Object to be Signed</name>
                    <t>
                        Use the result of the previous step as input to the
                        canonicalization process described in JCS
                        <xref target="RFC8785" format="default"/>.
                    </t>
                    <t>
                        Applied to the example, the following JSON string should be generated:
                    </t>
                    <sourcecode type="json">
{"otherProperties":[2000,true],"statement":"Hello signed world!"}
                    </sourcecode>
                    <t>
                        After encoding the string above in the UTF-8 <xref target="UNICODE" format="default"/>
                        format, the following bytes (here in hexadecimal notation) should be generated:
                    </t>
                    <sourcecode type="test-vectors">
7b 22 6f 74 68 65 72 50 72 6f 70 65 72 74 69 65 73 22 3a 5b 32 30
30 30 2c 74 72 75 65 5d 2c 22 73 74 61 74 65 6d 65 6e 74 22 3a 22
48 65 6c 6c 6f 20 73 69 67 6e 65 64 20 77 6f 72 6c 64 21 22 7d
                    </sourcecode>
                </section>
                <section anchor="signing.create.jws" numbered="true" toc="default">
                    <name>Generate a JWS String</name>
                    <t>
                        Use the result of the previous step as <tt>JWS&nbsp;Payload</tt> to the
                        signature process described in Appendix F of JWS <xref target="RFC7515" format="default"/>.
                    </t>
                    <t>
                        For the example, the JWS header is assumed to be:
                    </t>
                    <sourcecode type="json">
{"alg":"HS256"}
                    </sourcecode>
                    <t>
                        The resulting JWS string should then after payload removal
                        and using the key specified in <xref target="Operation" format="default"/>,
                        read as follows:
                    </t>
                    <sourcecode type="test-vectors">
eyJhbGciOiJIUzI1NiJ9..VHVItCBCb8Q5CI-49imarDtJeSxH2uLU0DhqQP5Zjw4
                    </sourcecode>
                </section>
                <section anchor="signing.final" numbered="true" toc="default">
                    <name>Assemble the Signed JSON Object</name>
                    <t>
                        Before a complete signed object can be created, a dedicated top-level
                        property for holding the JWS signature string needs to be defined.
                        The only requirement is that this property <bcp14>MUST NOT</bcp14> clash
                        with any other top-level property name.
                        The JWS string itself <bcp14>MUST</bcp14> be supplied as a
                        JSON string argument to the signature property.
                    </t>
                    <t>
                        For the example, the property name "signature"
                        is assumed to be the designated holder of the JWS string.
                        Equipped with a signature property, the JWS string from the previous
                        section, and the original JSON example, the process above should result
                        in the following, now signed JSON object (with a line break in the "signature" property
                        for display purposes only):
                    </t>
                    <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true],
  "signature": "eyJhbGciOiJIUzI1NiJ9..VHVItCBCb8Q5CI-49imar
DtJeSxH2uLU0DhqQP5Zjw4"
}
                    </sourcecode>
                </section>
            </section>
            <section anchor="validation" numbered="true" toc="default">
                <name>Signature Validation</name>
                <t>
                    The following sub-sections describe how JSON objects signed
                    according to the JWS/CT specification can be validated.
                </t>
                <section anchor="validation.parse.input" numbered="true" toc="default">
                    <name>Parse the Signed JSON Object</name>
                    <t>
                        Parse the JSON object that is expected to have been signed.
                        If the parsing is unsuccessful, the operation <bcp14>MUST</bcp14>
                        cause a compliant implementation to terminate
                        processing and return an error indication.
                    </t>
                    <t>
                        To illustrate the subsequent operations the signed JSON object
                        featured in <xref target="signing.final" format="default"/> is used as example.
                   </t>
                </section>
                <section anchor="validation.fetch.signprop" numbered="true" toc="default">
                    <name>Fetch the Signature Property String</name>
                    <t>
                        After successful parsing, retrieve the designated JSON top-level
                        property holding the JWS string.  If the property is missing
                        or its argument is not a JSON string value,
                        the operation <bcp14>MUST</bcp14>
                        cause a compliant implementation to terminate
                        processing and return an error indication.
                    </t>
                    <t>
                        For the example, where the property named "signature" is assumed to hold the JWS string,
                        the operation above should return the following string:
                   </t>
                    <sourcecode type="test-vectors">
eyJhbGciOiJIUzI1NiJ9..VHVItCBCb8Q5CI-49imarDtJeSxH2uLU0DhqQP5Zjw4
                    </sourcecode>
                </section>
                <section anchor="validation.remove.signprop" numbered="true" toc="default">
                    <name>Remove the Signature Property String</name>
                    <t>
                        Since the signature is calculated over the actual JSON object
                        data, the designated signature property and its argument <bcp14>MUST</bcp14>
                        be removed from the signed JSON object.
                    </t>
                    <t>
                        If applied to the example the resulting JSON object should read as follows:
                   </t>
                    <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true]
}
                    </sourcecode>
                    <t>
                        Note: JSON tools usually by default remove whitespace.
                        In addition, the original ordering of properties may
                        not always be honored.
                        However, none of this has (due to the canonicalization performed by JCS),
                        any impact on the result.
                    </t>
                </section>
                <section anchor="validation.canonicalize" numbered="true" toc="default">
                    <name>Canonicalize the Remaining JSON Object</name>
                    <t>
                        Use the result of the previous step as input to the
                        canonicalization process described in JCS
                        <xref target="RFC8785" format="default"/>.
                    </t>
                    <t>
                        If applied to the example the result of the process above should read as follows:
                   </t>
                    <sourcecode type="json">
{"otherProperties":[2000,true],"statement":"Hello signed world!"}
                    </sourcecode>
                    <t>
                        After encoding the string above in the UTF-8 <xref target="UNICODE" format="default"/>
                        format, the following bytes (here in hexadecimal notation) should be generated:
                    </t>
                    <sourcecode type="test-vectors">
7b 22 6f 74 68 65 72 50 72 6f 70 65 72 74 69 65 73 22 3a 5b 32 30
30 30 2c 74 72 75 65 5d 2c 22 73 74 61 74 65 6d 65 6e 74 22 3a 22
48 65 6c 6c 6f 20 73 69 67 6e 65 64 20 77 6f 72 6c 64 21 22 7d
                    </sourcecode>
                </section>
                <section anchor="validation.finalstep.jws" numbered="true" toc="default">
                    <name>Validate the JWS String</name>
                    <t>
                        After extracting the detached mode JWS string and canonicalizing the JSON object
                        (to retrieve the <tt>JWS&nbsp;Payload</tt>),
                        the JWS string <bcp14>MUST</bcp14> be restored as described in Appendix F of JWS
                        <xref target="RFC7515" format="default"/>.
                        The actual JWS validation procedure is not specified
                        here because it is covered by <xref target="RFC7515" format="default"/>
                        and also depends on application-specific policies like:
                    </t>
                    <ul spacing="compact">
                        <li>Accepted JWS signature algorithms</li>
                        <li>Accepted and/or required JWS header elements</li>
                        <li>Signature key lookup methods</li>
                    </ul>
                    <t>
                        If the validation process for some reason fails,
                        the operation <bcp14>MUST</bcp14>
                        cause a compliant implementation to terminate 
                        processing and return an error indication.
                    </t>
                    <t>
                        For the example, validation is straightforward since both the algorithm and
                        the key to use are predefined (see <xref target="Operation" format="default"/>).
                        The input string to a JWS validator should after the process step above read
                        as follows (with line breaks for display purposes only):
                    </t>
                    <sourcecode type="test-vectors">
eyJhbGciOiJIUzI1NiJ9.eyJvdGhlclByb3BlcnRpZXMiOlsyMDAwLHRydWVdLCJzdGF0
ZW1lbnQiOiJIZWxsbyBzaWduZWQgd29ybGQhIn0.VHVItCBCb8Q5CI-49imarDtJeSxH2
uLU0DhqQP5Zjw4
                    </sourcecode>
                </section>
            </section>
        </section>
        <section anchor="IANA" numbered="true" toc="default">
            <name>IANA Considerations</name>
            <t>
                This document has no IANA actions.
            </t>
        </section>
        <section anchor="Security" numbered="true" toc="default">
            <name>Security Considerations</name>
            <t>
                This specification inherits all the security considerations
                of JWS <xref target="RFC7515" format="default"/>
                and JCS <xref target="RFC8785" format="default"/>.
            </t>
            <t>
                In similarity to any other signature specification,
                it is crucial that signatures are verified before
                acting on the signed payload.
            </t>
            <t>
                However, poorly tested software components may also introduce
                security issues.  Consider the following JSON example:
            </t>
            <sourcecode type="json">
{
  "fromAccount": "1234",
  "toAccount": "4567",
  "amount": {
    "value": 100,
    "currency":"USD"
  }
}
            </sourcecode>
            <t>
                A non-compliant JCS implementation could return
            </t>
            <sourcecode type="json">
{"amount":{},"fromAccount":"1234","toAccount":"4567"}
            </sourcecode>
            <t>
                giving an attacker the ability to change "amount" to whatever it wants.
                Note though that this attack presumes that the consumer and producer use 
                implementations broken in the same way, otherwise the signature would not validate.
            </t>
            <t>
                For usage in a wider community, the name of the designated
                signature property becomes a critical factor that
                <bcp14>MUST</bcp14> be documented and communicated.
                However, in a properly designed system, a faulty or
                missing signature <bcp14>MUST</bcp14> "only" lead to
                failed operation, and not to a security breach.
            </t>
        </section>
    </middle>
    <back>
        <references>
            <name>References</name>
            <references>
                <name>Normative References</name>

                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7493.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7515.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7518.xml"/>
                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8785.xml"/>

                <reference anchor="UNICODE"
                   target="https://www.unicode.org/versions/latest/">
                    <front>
                        <title>The Unicode Standard</title>
                        <author>
                            <organization>The Unicode Consortium</organization>
                        </author>
                    </front>
                </reference>

            </references>
            <references>

                <name>Informative References</name>

                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7797.xml"/>

                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7517.xml"/>

                <xi:include
                    href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml"/>

                <reference anchor="XMLDSIG"
                   target="https://www.w3.org/TR/xmldsig-core1/">
                    <front>
                        <title>XML Signature Syntax and Processing Version 1.1</title>
                        <author>
                            <organization>W3C</organization>
                        </author>
                        <date month="April" year="2013"/>
                    </front>
                    <refcontent>W3C Recommendation</refcontent>
                </reference>

                <reference anchor="SHS"
                   target="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">
                    <front>
                        <title>Secure Hash Standard (SHS)</title>
                        <author>
                            <organization>NIST</organization>
                        </author>
                        <date month="August" year="2015"/>
                    </front>
                    <refcontent>FIPS PUB 180-4</refcontent>
                </reference>
            </references>
        </references>

        <section anchor="open.source" numbered="true" toc="default">
            <name>Open-Source Implementations</name>
            <t>
                Due to the simplicity of this specification, there is hardly a need for
                specific support software.
                However, JCS which is (at the time of writing), a relatively new design,
                may be fetched as a separate component for multiple platforms.
                The following open-source implementations have been verified to be
                compatible with JCS:
            </t>
            <ul spacing="normal">
                <li>
                    JavaScript: <eref
      target="https://www.npmjs.com/package/canonicalize"
      brackets="angle"/>
                </li>
                <li>
                    Java: <eref
            target="https://mvnrepository.com/artifact/io.github.erdtman/java-json-canonicalization"
            brackets="angle"/>
                </li>
                <li>
                    Go: <eref
              target="https://github.com/cyberphone/json-canonicalization/tree/master/go"
                brackets="angle"/>
                </li>
                <li>
                    .NET/C#: <eref
         target="https://github.com/cyberphone/json-canonicalization/tree/master/dotnet"
           brackets="angle"/>
                </li>
                <li>
                    Python: <eref
          target="https://github.com/cyberphone/json-canonicalization/tree/master/python3"
            brackets="angle"/>
                </li>
            </ul>
        </section>

        <section anchor="jws-ct.applications" numbered="true" toc="default">
            <name>JWS/CT Application Notes</name>
            <t>
                The following application notes are not a part of the JWS/CT core; they show
                how JWS/CT can be used in contexts involving multiple signatures.
            </t>
            <section anchor="counter.signatures" numbered="true" toc="default">
                <name>Counter-Signatures</name>
                <t>
                    Consider the following JWS/CT object showing an imaginary
                    real estate business record
                    (with a line break in the "signature" property for display purposes only):
                </t>
                <sourcecode type="json">
{
  "gps": [38.89768255588178, -77.03658644893932],
  "object": {
    "type": "house",
    "price": "$635,000"
  },
  "role": "buyer",
  "name": "John Smith",
  "timeStamp": "2020-11-08T13:56:08Z",
  "signature": "eyJhbGciOiJIUzI1NiJ9..zlPMniQiz4Eie86oK4xo25z
uyW92csiDqyiQrF6R5ug"
}
                </sourcecode>
                <t>
                    The signature above was created using the example key from
                    <xref target="Operation" format="default"/>.
                </t>
                <t>
                    Adding a notary signature on top of this could be performed
                    by embedding the former object as follows
                    (with line breaks in the "signature" properties for display purposes only):
                </t>
                <sourcecode type="json">
{
  "attesting": {
    "gps": [38.89768255588178, -77.03658644893932],
    "object": {
      "type": "house",
      "price": "$635,000"
    },
    "role": "buyer",
    "name": "John Smith",
    "timeStamp": "2020-11-08T13:56:08Z",
    "signature": "eyJhbGciOiJIUzI1NiJ9..zlPMniQiz4Eie86oK4xo25z
uyW92csiDqyiQrF6R5ug"
  },
  "role": "notary",
  "name": "Carol Lombardi-Jones",
  "timeStamp": "2020-11-08T13:58:42Z",
  "signature": "eyJhbGciOiJFUzI1NiJ9..AVmJGUWp1JD0pf2j1_UQWXbf-
qj-2RWxOnyAXihd4POKbnjWqqSBmHPNfgMQFH_s5sXHkIOkDZe2nShqEJOEVA"
}
                </sourcecode>
                <t>
                    A side effect of this arrangement is that the notary's signature signs
                    not only the notary data, but the buyer's data and signature as well.
                    In most cases this way of adding signatures is advantageous since it
                    maintains the actual order of signing events which also cannot
                    be tampered with without invalidating the outermost signature.
                </t>
                <t>
                    Note that all properties above including "signature" are
                    application specific.
                </t>
                <t>
                    The notary's signature was created using the example key from
                    <xref target="alt.algorithm" format="default"/>.
                </t>
            </section>

            <section anchor="detached.signatures" numbered="true" toc="default">
                <name>Detached Signatures</name>
                <t>
                    In the case the signing entities are "peers" or are unrelated
                    to each other, counter-signatures like described in
                    <xref target="counter.signatures" format="default"/>
                    are not applicable since they presume a specific flow.
                    For supporting independent or asynchronous 
                    signers targeting a common document or data object,
                    an imaginable solution is using a scheme where each signer
                    calculates a hash of the target document/data and includes the hash 
                    together with signer-specific meta data like the following:
                </t>
                <sourcecode type="json">
{

  &lt;&lt;Common Document/Data to Sign...&gt;&gt;

  "signers": [{
    "sha256": "&lt;&lt;Hash of Document/Data to Sign&gt;&gt;",

    &lt;&lt;Signer-related meta data...&gt;&gt;

    "signature": "&lt;&lt;Signer JWS Signature&gt;&gt;"
  },{
    "sha256": "&lt;&lt;Hash of Document/Data to Sign&gt;&gt;",

    &lt;&lt;Signer-related meta data...&gt;&gt;

    "signature": "&lt;&lt;Signer JWS Signature&gt;&gt;"
  }]
}
                </sourcecode>
                <t>
                    In this case the object to sign would not be limited to JSON;
                    it could, for example, be a PDF document hosted on a specific URL.
                    Note that the relying party would have to update the structure for each signature received.
                    In some cases a database would probably be more useful for holding individual signatures
                    since a database can cope with any number of signers as well as keeping track of who
                    have actually signed.  The latter is crucial for things like international treaties and
                    company board statements.
                </t>
                <t>
                    Note that although "signers", "sha256", and "signature" are
                    application specific property names, the objects in the
                    "signers" array are assumed to be fully conformant with the
                    JWS/CT specification.
                </t>
                <t>
                    The following example shows a possible detached signature solution
                    (with line breaks in the "signature" properties for display purposes only):
                </t>
                <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true],
  "signers": [{
    "sha256": "n-i0HIBJKELoTicCK9c5nqJ8cYH0znGRcEbYKoQfm70",
    "timeStamp": "2020-11-18T07:45:28Z",
    "name": "Alice",
    "signature": "eyJhbGciOiJIUzI1NiJ9..AE7CnzSYsaspE3yrdsAwi
avd3IdWtdAmDE8FRMwYLA8"
  },{
    "sha256": "n-i0HIBJKELoTicCK9c5nqJ8cYH0znGRcEbYKoQfm70",
    "timeStamp": "2020-11-18T08:03:40Z",
    "name": "Bob",
    "signature": "eyJhbGciOiJFUzI1NiJ9..0tNLy0pLcHUjPhhorpKd5
7a8zTPeqlrOjATiSlPQ1vciE99x6mHmow04tPbJS8dqSqO9c4RkKW6jeL4ZyWpXLA"
  }]
}
                </sourcecode>
                <t>
                    Notes:
                </t>
                <ul>
                    <li>"Alice" used the example key from <xref target="Operation" format="default"/>
                        while "Bob" used the example key specified in <xref target="alt.algorithm" format="default"/>.
                    </li>
                    <li>
                        The "sha256" properties hold base64url-encoded
                        <xref target="RFC4648" format="default"/>, SHA256-hashes
                        <xref target="SHS" format="default"/> of the canonicalized
                        data created in <xref target="signing.canonicalize" format="default"/>.
                    </li>
                    <li>
                        This arrangement requires a two-step validation process where
                        each JWS/CT object in the "signers" array is individually validated,
                        as well as having its "sha256" property compared with the actual hash
                        of the canonicalized common data.
                    </li>
                </ul>
            </section>

            <section anchor="array.signatures" numbered="true" toc="default">
                <name>Array of Signatures</name>
                <t>
                    Another possibility supporting multiple and independent
                    signatures is collecting JWS signature strings in a JSON array object
                    according to the following scheme:
                </t>
                <sourcecode type="json">
{

  &lt;&lt;Common Document/Data to Sign...&gt;&gt;

  "&lt;&lt;Signature property&gt;&gt;": ["&lt;&lt;Signature-1&gt;&gt;",
                             "&lt;&lt;Signature-2&gt;&gt;",
                                       .
                             "&lt;&lt;Signature-n&gt;&gt;"]
}
                </sourcecode>
                <t>
                    Processing would follow <xref target="Operation" format="default"/>,
                    with the addition that each signature is dealt with individually.
                </t>
                <t>
                    Compared to <xref target="detached.signatures" format="default"/>,
                    signature arrays imply that possible signer-specific meta-data
                    is supplied as JWS extensions in the associated signature's base64url-encoded header.
                </t>
                <t>
                    By combining the example used in <xref target="Operation" format="default"/>
                    with the test vector in <xref target="alt.algorithm" format="default"/>, a valid
                    signature array object could be as follows (with line breaks in the "signatures"
                    property for display purposes only):
                </t>
                <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true],
  "signatures": ["eyJhbGciOiJIUzI1NiJ9..VHVItCBCb8Q5CI-49imar
DtJeSxH2uLU0DhqQP5Zjw4",
                 "eyJhbGciOiJFUzI1NiJ9..ENP0j0-QPsA7N_Mg1-RMN
9IxapeTWtQwR7sPUqEiSNHPuV_fqSdRqqkLOlBdV01cc4lSJdn1XCv-ZHYdZ9t3kA"]
}
                </sourcecode>
                <t>
                    Note that "signatures" is not a keyword, it was only selected
                    to highlight the fact that there are multiple signatures.
                </t>
            </section>

        </section>

        <section anchor="alt.algorithm" numbered="true" toc="default">
            <name>Test Vector Using the ES256 Algorithm</name>
            <t>
                This appendix shows how a signed version of the JSON example object in
                <xref target="signing.data.creation" format="default"/> would look like
                if applying the <tt>ES256</tt> JOSE algorithm
                <xref target="RFC7518" format="default"/>
                (with a line break in the "signature" property for display purposes only):
            </t>
            <sourcecode type="json">
{
  "statement": "Hello signed world!",
  "otherProperties": [2000, true],
  "signature": "eyJhbGciOiJFUzI1NiJ9..ENP0j0-QPsA7N_Mg1-RMN
9IxapeTWtQwR7sPUqEiSNHPuV_fqSdRqqkLOlBdV01cc4lSJdn1XCv-ZHYdZ9t3kA"
}
            </sourcecode>
            <t>
                The example above depends on a JWS header holding the algorithm
                {"alg":"ES256"}, and the following private key, here expressed in
                the JWK <xref target="RFC7517" format="default"/> format:

            </t>
            <sourcecode type="json">
{
  "kty": "EC",
  "crv": "P-256",
  "x": "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
  "y": "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg",
  "d": "6XxMFXhcYT5QN9w5TIg2aSKsbcj-pj4BnZkK7ZOt4B8"
}
            </sourcecode>
            <t>
                Note that signing with the <tt>ES256</tt> algorithm returns different
                results for each signature due to a randomization step
                in the signature computation process. 
            </t>
        </section>

        <section anchor="alt.mode" numbered="true" toc="default">
            <name>Enhanced JWS Processing Option</name>
            <t>
                By default, JWS/CT uses the JWS compact serialization mode "as is".
                As a consequence, a technically redundant, internal-only,
                base64url encoding step is performed over the <tt>JWS&nbsp;Payload</tt>.
                Although the performance hit should be marginal for most real-world applications,
                a possibility is using the "Unencoded Payload" mode of RFC7797
                <xref target="RFC7797" format="default"/>.
                However, this requires that the JWS implementation supports the
                "b64":false and "crit":["b64"] header elements implied by RFC7797,
                effectively rendering the RFC7797 mode as an 
                implementer option for specific communities.
            </t>
        </section>

        <section anchor="Acknowledgements" numbered="false" toc="default">
            <name>Acknowledgements</name>
            <t>
                People who have contributed directly and indirectly with
                valuable input to this specification include
                <contact fullname="Vladimir Dzhuvinov"/>,
                <contact fullname="Freddi Gyara"/>,
                and
                <contact fullname="Filip Skokan"/>.
            </t>
        </section>
        <section anchor="document.history" numbered="false" toc="default">
            <name>Document History</name>
            <t>
                [[ This section to be removed by the RFC Editor before publication as
                an RFC ]]
            </t>
            <t>Version 00:</t>
            <ul spacing="normal">
                <li>
                    Initial publication.
                </li>
            </ul>
            <t>Version 01:</t>
            <ul spacing="normal">
                <li>
                    Added paragraph to Abstract.
                </li>
                <li>
                    Updated Security Considerations.
                </li>
            </ul>
            <t>Version 02:</t>
            <ul spacing="normal">
                <li>
                    Changed alternative test key to ES256/P-256.
                </li>
                <li>
                    Moved RFC7797 to an appendix.
                </li>
                <li>
                    Changed &lt;tt&gt; to only be used on keywords.
                </li>
                <li>
                    Added some clarity to detached signatures.
                </li>
            </ul>
          <t>Version 03:</t>
          <ul spacing="normal">
            <li>
              Language changes suggested by ISE.
            </li>
          </ul>
          <t>Version 04:</t>
          <ul spacing="normal">
            <li>
              Language nit.
            </li>
          </ul>
          <t>Version 05:</t>
          <ul spacing="normal">
            <li>
              Document refresh.
            </li>
          </ul>
          <t>Version 06:</t>
          <ul spacing="normal">
            <li>
              Changes after ISE review.
            </li>
          </ul>
          <t>Version 07:</t>
          <ul spacing="normal">
            <li>
              Changes after ISE and external reviews.
            </li>
          </ul>
       </section>
    </back>
</rfc>
