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

<?xml-model href="rfc7991bis.rnc"?> 

<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
  <!ENTITY pm     "&#xb1;">
]>

<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="info"
  docName="draft-rundgren-universal-cbor-04"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3">

  <front>
    <title abbrev="U-CBOR">Universal CBOR (U-CBOR)</title>

    <seriesInfo name="Internet-Draft" value="draft-rundgren-universal-cbor-04"/>
   
    <author fullname="Anders Rundgren" initials="A." surname="Rundgren" role="editor">
        <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="2025"/>

    <area>Application</area>
    <workgroup>Internet Engineering Task Force</workgroup>

    <keyword>CBOR</keyword>
    <keyword>Deterministic</keyword>
    <keyword>Encoding</keyword>
    <keyword>Cryptography</keyword>
    <keyword>Enveloped</keyword>
    <keyword>Signature</keyword>

    <abstract>
      <t>
This document defines Universal CBOR (U-CBOR),
a strict subset of CBOR (RFC 8949)
intended to serve as a viable replacement for JSON in
computationally advanced systems like Internet browsers,
mobile phones, and Web servers.
To foster interoperability, deterministic encoding
is mandated.  Furthermore, the document outlines how
deterministic encoding combined with enhanced CBOR tools,
enable cryptographic methods like signing and hashing,
to optionally use "raw" (non-wrapped) CBOR data as input.
This document mainly targets CBOR tool developers.
      </t>
    </abstract>
 
  </front>

  <middle>
    
    <section>
      <name>Introduction</name>
          <t>
The Universal CBOR (U-CBOR) specification is based on CBOR <xref target="RFC8949"/>.
While there are different ways you can encode certain CBOR objects,
this is non-trivial to support in general purpose platform-based tools,
not to mention the limited utility of such measures.
To cope with this, U-CBOR defines a specific (non-variant) encoding scheme,
aka &quot;Deterministic Encoding&quot;.  The selected encoding
scheme is believed to be <em>compatible</em> with most existing
<em>systems</em> using CBOR.
See also <xref target="legacy.systems"/>.
        </t>
    <t>
U-CBOR is intended to be agnostic with respect to programming
languages.
        </t>
        <t>
By combining the compact binary representation and the rich set of
data types offered by CBOR, with a deterministic encoding scheme,
U-CBOR could for <em>new designs</em>, serve as viable alternative
to JSON <xref target="RFC8259"/>.
Although the mandated encoding scheme is deployable in
<xref target="CONSTRAINED"/> environments, the primary target is rather
general-purpose computing platforms like mobile phones and Web servers.
    </t>
        <t>
However, for unleashing the full power of deterministic encoding,
the ability to perform cryptographic operations on "raw" (non-wrapped)
CBOR data, compliant U-CBOR tools need additional functionality.
See also <xref target="enveloped.signatures"/>.
        </t>
        <t>
<xref target="detailed.description"/> contains the
actual specification.
        </t>
      
      <section>
        <name>Requirements Language</name>
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
          "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
          RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
          interpreted as described in BCP 14 <xref target="RFC2119"/>
          <xref target="RFC8174"/> when, and only when, they appear in
          all capitals, as shown here.</t>
      </section>

      <section>
        <name>Common Definitions</name>
<ul>
<li>This document uses the conventions defined in CDDL <xref target="RFC8610"/> 
for expressing the type of CBOR <xref target="RFC8949"/> data items.</li>
<li>Examples showing CBOR data, are expressed in "diagnostic notation" as defined
in <xref section="8" sectionFormat="of"  target="RFC8949"/>.</li>
<li>The term "CBOR&nbsp;object" is equivalent to "CBOR&nbsp;data&nbsp;item"
used in <xref target="RFC8949"/>.</li>
<li>The term "Universal CBOR" is in this document abbreviated to "U-CBOR".</li>
</ul>
      </section>

    </section>
    
    <section anchor="detailed.description">
      <name>Detailed Description</name>
      <t>This section describes the three pillars that U-CBOR relies on.</t>

      <section anchor="ucbor.objects">
        <name>Supported CBOR Objects</name>
        <t>The following table shows the CBOR subset supported by U-CBOR:</t>
<table>
<name>Supported CBOR Objects</name>
<thead>
  <tr><th align="center">CDDL</th>
  <th align="center">Description</th></tr>
</thead>
<tbody>
<tr><td align="center"><tt>int</tt></td><td>Integer</td></tr>
<tr><td align="center"><tt>bigint</tt></td><td>Big integer</td></tr>
<tr><td align="center"><tt>float</tt></td><td>16-, 32-, and 64-bit <xref target="IEEE754"/> numbers</td></tr>
<tr><td align="center"><tt>tstr</tt></td><td>Text string encoded as UTF-8 <xref target="RFC3629"/></td></tr>
<tr><td align="center"><tt>bstr</tt></td><td>Byte string</td></tr>
<tr><td align="center"><tt>bool</tt></td><td>Boolean <tt>true</tt> and <tt>false</tt></td></tr>
<tr><td align="center"><tt>null</tt></td><td>Represents a <tt>null</tt> object</td></tr>
<tr><td align="center"><tt>[]</tt></td><td>Array</td></tr>
<tr><td align="center"><tt>{}</tt></td><td>Map</td></tr>
<tr><td align="center"><tt>#6.nnn(type)</tt></td><td>Tagged data</td></tr>
</tbody>
</table>
        <t>
Conforming implementations (of course) only have to implement the U-CBOR types
required by the targeted application(s).
        </t>
        <t>
Although extensions are imaginable (like supporting all
"simple" types), extensions will most likely cause
<em>interoperability issues</em> and are thus NOT&nbsp;RECOMMENDED.  In addition,
the mandated CBOR subset is compatible with most computer languages and platforms.
Compared to the current state-of-the-art, JSON <xref target="RFC8259"/>,
the availability of <tt>bigint</tt>, <tt>bstr</tt>, and "tagged data"
represent major improvements.
  </t>
  <t>
However, nothing prevents developers from at the application (API) level, 
through mapping concepts, support additional, "virtual" data types,
analogous to how you map an application's data model to the
set of data types available, be it a data interchange format,
a database, or a programming language.
</t>
<t>
OpenAPI <xref target="OPENAPI"/> is an example of an API which defines
data types through mapping.
</t>


      </section>
      
      <section anchor="ucbor.encoding">
        <name>Deterministic Encoding Scheme</name>
        <t>
In U-CBOR deterministic encoding is <em>mandatory</em>.
The encoding scheme adheres to <xref section="4.2" sectionFormat="of" target="RFC8949"/>,
but adds a few constraints (denoted by RFC+), where the RFC offers choices.
The following list contains a summary of the U-CBOR deterministic encoding rules:
        </t>
      <ul>
        <li>
RFC+: Floating-point and integer objects MUST be treated as <em>distinct types</em>
regardless of their numeric value. This is compliant with
Rule&nbsp;2 in <xref section="4.2.2" sectionFormat="of" target="RFC8949"/>.
        </li>
        <li>
        <t>
RFC: Integers, represented by the <tt>int</tt> and
<tt>bigint</tt> types, MUST use the <tt>int</tt>
type if the value is between <tt>-2<sup>64</sup></tt>
and <tt>2<sup>64</sup>-1</tt>,
otherwise the <tt>bigint</tt> type MUST be used.
<xref target="ucbor.integers"/>
features a list of compliant integer sample values.
        </t>
        </li>
        <li>
        <t>
RFC+: Floating-point numbers MUST always use the shortest
<xref target="IEEE754"/> variant that
preserves the precision of the original value.
<xref target="ucbor.floats"/>
features a list of compliant floating-point sample values.
        </t>
        <t>
Note that <tt>NaN</tt> "signaling" (like <tt>f97e01</tt>),
MUST be <em>rejected</em>.
        </t>
        </li>
        <li><t>
RFC: Map keys MUST be sorted in the bytewise lexicographic
order of their deterministic encoding.
Duplicate keys MUST be <em>rejected</em>.
Somewhat surprisingly the following represents a properly sorted map:</t>
<sourcecode name="Ordered map" type="cbor">
<![CDATA[{
  "a": ... ,
  "b": ... ,
  "aa": ...
}]]></sourcecode>
        </li>
        <li>
RFC+: Since CBOR encodings according to this specification
maintain uniqueness, there are no specific restrictions or
tests needed in order to determine map key equivalence.
As an (extreme) example, the floating-point numbers <tt>0.0</tt> and
<tt>-0.0</tt>, and the integer number <tt>0</tt>
could represent the distinct keys
<tt>f90000</tt>, <tt>f98000</tt>, and <tt>00</tt> respectively.
        </li>
        <li>
RFC: Indefinite length objects MUST be <em>rejected</em>.
        </li>
      </ul>
      </section>
      
      <section anchor="ucbor.tools">
        <name>CBOR Tool Requirements</name>
<t>
The primary feature that deterministic encoding brings to the table is
that wrapping CBOR data to be signed in <tt>bstr</tt> objects, like
specified by COSE in <xref section="2" sectionFormat="of" target="RFC9052"/>,
no longer is a prerequisite.
That is, cryptographic operations can <em>optionally</em> be performed
on "raw" CBOR data.
Turn to <xref target="enveloped.signatures"/> for
an example of an application depending on such features.
</t>
<t>
However, to make this a reality, the following functionality MUST be
provided by CBOR tools compliant with this specification:
</t>
<ul>
 <li>
  Decoded CBOR primitives MUST remain <em>immutable</em>, regardless if they are stand-alone
  or being a part of a tagged object like
  <tt>bigfloat</tt> (see <xref section="3.4.4" sectionFormat="of"  target="RFC8949"/>).
  </li>
   <li>
  It MUST be possible to find out the type of a CBOR object, <em>before</em> it is accessed.
  </li>
  <li>
  It MUST be possible to <em>add</em>, <em>delete</em>, and
  <em>update</em> the contents of CBOR <tt>map</tt> and <tt>array</tt> objects,
  of decoded CBOR data.
  </li>
  <li>
  It MUST be possible to <em>reserialize</em> decoded CBOR data,
  be it updated or not.
  </li>
  <li>
  Irrespective of if CBOR data was decoded, updated, or created 
  programmatically, deterministic encoding MUST be maintained.
  </li>
    <li>
  Invalid or unsupported CBOR constructs, as well as CBOR data not adhering
  to the deterministic encoding scheme MUST be <em>rejected</em>.
  See also <xref target="legacy.systems"/> and <xref target="ucbor.invalid"/>.
  </li>
</ul>
<t>
As a consequence of these rules, CBOR data and application / platform-level data,
MUST be <em>separated</em> for cases where <em>reserialization</em>
could present a problem, like in this Chrome browser console example:
</t>
<sourcecode name="Platform issues" type="cbor">
<![CDATA[> let date = new Date('2025-03-02T13:08:55.0001+03:00');
> date.toISOString()
'2025-03-02T10:08:55.000Z']]>
</sourcecode>
<t>
How this separation actually is accomplished is out of scope for this specification.
However, <em>encapsulation</em> of CBOR data in <em>high-level</em>, and
<em>self-rendering objects</em>, represents an established method,
featured in similar tools for ASN.1.
The code in <xref target="example.code"/> shows an example
that <em>updates</em> and <em>reserializes</em> decoded CBOR data.
</t>

        <section anchor="platform.numbers">
        <name>Protocol Primitives Support</name>
        <t>
To facilitate cross-platform <em>protocol interoperability</em>,
implementers of U-CBOR compatible tools SHOULD include <em>decoder</em>
API support for the following primitives:
        </t>
<table>
<name>Protocol Primitives Support</name>
<thead>
  <tr>
  <th align="center">CDDL</th>
  <th align="center">Primitive</th>
  <th align="center">Description</th>
  <th align="center">Note</th>
  </tr>
</thead>
<tbody>
<tr>
<td align="center"><tt>int</tt></td>
<td align="center"><tt>Int8</tt></td>
<td>8-bit signed integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>uint</tt></td>
<td align="center"><tt>Uint8</tt></td>
<td>8-bit unsigned integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>int</tt></td>
<td align="center"><tt>Int16</tt></td>
<td>16-bit signed integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>uint</tt></td>
<td align="center"><tt>Uint16</tt></td>
<td>16-bit unsigned integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>int</tt></td>
<td align="center"><tt>Int32</tt></td>
<td>32-bit signed integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>uint</tt></td>
<td align="center"><tt>Uint32</tt></td>
<td>32-bit unsigned integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>int</tt></td>
<td align="center"><tt>Int64</tt></td>
<td>64-bit signed integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>uint</tt></td>
<td align="center"><tt>Uint64</tt></td>
<td>64-bit unsigned integer</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><tt>int</tt>&nbsp;/ <tt>bigint</tt></td>
<td align="center"><tt>BigInt</tt></td>
<td>Integer of arbitrary size</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><tt>float16</tt></td>
<td align="center"><tt>Float16</tt></td>
<td>16-bit floating-point number</td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><tt>float16</tt>&nbsp;/ <tt>float32</tt></td>
<td align="center"><tt>Float32</tt></td>
<td>32-bit floating-point number</td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><tt>float</tt></td>
<td align="center"><tt>Float64</tt></td>
<td>64-bit floating-point number</td><td>
</td>
</tr>
<tr>
<td align="center"><tt>bool</tt></td>
<td align="center"><tt>Boolean</tt></td>
<td>Boolean</td>
<td></td>
</tr>
<tr>
<td align="center"><tt>null</tt></td>
<td align="center"><tt>Null</tt></td>
<td>Null</td>
<td align="center">4</td>
</tr>
<tr>
<td align="center">See note</td>
<td align="center"><tt>EpochTime</tt></td>
<td>Time-object expressed as a number</td>
<td align="center">5</td>
</tr>
<tr>
<td align="center">See note</td>
<td align="center"><tt>DateTime</tt></td>
<td>Time-object expressed as a text string</td>
<td align="center">5</td>
</tr>
</tbody>
</table>
<ol>
<li>
<t>Range testing MUST be performed using the traditional ranges for
<em>unsigned</em> respectively <em>two-complement</em> numbers.
That is, a hypothetical <tt>getUint8()</tt> MUST reject numbers
outside of <tt>0</tt> to <tt>255</tt>,
whereas a hypothetical <tt>getInt8()</tt>,
MUST reject numbers outside of <tt>-128</tt> to <tt>127</tt>.
</t>
</li>
<li>
<t>
Note that a hypothetical <tt>getBigInt()</tt> MUST also accept CBOR <tt>int</tt>
objects since <tt>int</tt> is used for integers that fit in
CBOR major type 0 and 1 objects. 
See also <xref target="ucbor.integers"/> and <xref target="legacy.systems"/>.
</t>
</li>
<li>
<t>
Some platforms do not natively support <tt>float32</tt> and/or <tt>float16</tt>.
In this case a hypothetical <tt>getFloat16()</tt> would
need to use a bigger floating-point type for the return value.
</t>
<t>
Note that a hypothetical <tt>getFloat16()</tt> MUST reject encountered
<tt>Float32</tt> and <tt>Float64</tt> objects.  See also <xref target="legacy.systems"/>.
</t>
</li>
<li>
<t>
Since a CBOR <tt>null</tt> typically represents the absence of a value,
a decoder MUST provide a test-function, like <tt>isNull()</tt>.
</t>
</li>
<li>
<t>
Since CBOR does not feature a native-level time-object,
<xref section="3.4" sectionFormat="of"  target="RFC8949"/>
introduces two variants of time-objects using the 
CBOR tags <tt>0</tt> and <tt>1</tt>.
The time-objects SHOULD also be supported without the
tag construct.
</t>
</li>
</ol>
<t>
If a call does not match the underlying CDDL type, the call MUST be rejected,
</t>
<t>
Due to considerable variations between platforms, corresponding <em>encoder</em>
API support does not appear to be meaningful to specify in detail:
Java doesn't have built-in support for unsigned integers, whereas
JavaScript requires the use of the JavaScript <tt>BigInt</tt> type
for dealing with 64-bit integers.
</t>
      </section>


<section anchor="diagnostic.notation">
<name>Diagnostic Notation Support</name>
<t>Compliant U-CBOR implementations SHOULD include support for
<em>bi-directional</em> diagnostic notation, to facilitate:</t>
<ul>
<li>Human-centric debugging and logging</li>
<li>Easy creation of test and configuration data</li>
</ul>
<t>
The supported notation is compliant with a subset of 
<xref section="8" sectionFormat="of"  target="RFC8949"/>
(<tt>b32'</tt> and encoding indicators were left out),
but adds a few items to make diagnostic notation
slightly more adapted for parsing, like single-line comments:
</t>

<table>
<name>Diagnostic Notation Support</name>
<thead>
  <tr>
  <th align="center">CDDL</th>
  <th align="center">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Syntax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
  <th align="center">Description</th>
  <th align="center">Notes</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td></td>
    <td align="center"><tt>/</tt>&nbsp;<em>comment&nbsp;text</em>&nbsp;<tt>/</tt></td>
    <td>
      Multi-line comment.
      Multi-line comments are treated as whitespace and may thus also be used
      <em>between</em> CBOR objects.
    </td>
    <td align="center">6</td>
  </tr>
  <tr>
    <td></td>
    <td align="center"><tt>#</tt>&nbsp;<em>comment&nbsp;text</em></td>
    <td>
      Single-line comment.
      Single-line comments are terminated by a newline character (<tt>'\n'</tt>) or <tt>EOF</tt>.
      Single-line comments may also terminate lines holding regular CBOR items.
    </td>
    <td align="center">6</td>
  </tr>
  <tr>
    <td align="center"><tt>int</tt>&nbsp;/ <tt>bigint</tt></td>
    <td align="center">{<em>sign</em>}{<tt>0b</tt>|<tt>0o</tt>|<tt>0x</tt>}<em>n</em></td>
    <td>
      Arbitrary sized integers without fractional components or exponents.
      See also CBOR integer encoding.
      For <em>input</em> data in diagnostic notation, binary, octal, and hexadecimal notation
      is also supported by prepending numbers with <tt>0b</tt>, <tt>0o</tt>, and <tt>0x</tt> respectively.
      The latter also permit arbitrary insertions of <tt>'_'</tt> characters between digits to
      enable grouping of data like <tt>0b100_000000001</tt>.
    </td>
    <td align="center">1, 2</td>
  </tr>
  <tr>
    <td align="center"><tt>float16</tt>&nbsp;/ <tt>float32</tt>&nbsp;/ <tt>float64</tt></td>
    <td align="center">{<em>sign</em>}<em>n</em><tt>.</tt><em>n</em>{<tt>e&pm;</tt><em>n</em>}</td>
    <td>
      Floating point values MUST include a decimal point and at least one
      fractional digit, whereas exponents are <em>optional</em>.
    </td>
    <td align="center">1, 2</td>
  </tr>
  <tr>
    <td align="center"><tt>float16</tt></td>
    <td align="center"><tt>NaN</tt></td>
    <td>
      Not a number.
    </td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>float16</tt></td>
    <td align="center">{<em>sign</em>}<tt>Infinity</tt></td>
    <td>
      Infinity.
    </td>
    <td align="center">2</td>
  </tr>
  <tr>
    <td align="center"><tt>bstr</tt></td>
    <td align="center"><tt>h'</tt><em>hex&nbsp;data</em><tt>'</tt></td>
    <td>
      Byte data provided in hexadecimal notation.
      Each byte MUST be represented by two hexadecimal digits.
    </td>
    <td align="center">3</td>
  </tr>
  <tr>
    <td align="center"><tt>bstr</tt></td>
    <td align="center"><tt>b64'</tt><em>base64&nbsp;data</em><tt>'</tt></td>
    <td>
      Byte data provided in base64 or base64URL notation.
      Padding with <tt>'='</tt> characters is <em>optional</em>.
    </td>
    <td align="center">3, 6</td>
  </tr>
  <tr>
    <td align="center"><tt>bstr</tt></td>
    <td align="center"><tt>'</tt><em>text</em><tt>'</tt></td>
    <td>Byte data provided as UTF-8 encoded text.</td>
    <td align="center">4,&nbsp;5,&nbsp;6</td>
  </tr>
  <tr>
   <td align="center"><tt>bstr</tt></td>
    <td align="center"><tt>&lt;&lt;</tt>&nbsp;{<em>object</em>, }...&nbsp;<tt>&gt;&gt;</tt></td>
    <td>Construct holding zero or more comma-separated CBOR objects
    which are subsequently wrapped in a byte-string.</td>
    <td align="center">6</td>
  </tr>
  <tr>
    <td align="center"><tt>tstr</tt></td>
    <td align="center"><tt>&quot;</tt><em>text</em><tt>&quot;</tt></td>
    <td>UTF-8 encoded text-string.</td>
    <td align="center">4, 5</td>
  </tr>
  <tr>
    <td align="center"><tt>bool</tt></td>
    <td align="center"><tt>true</tt> | <tt>false</tt></td>
    <td>Boolean value.</td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>null</tt></td>
    <td align="center"><tt>null</tt></td>
    <td>Null value.</td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>[]</tt></td>
    <td align="center"><tt>[</tt>&nbsp;{<em>object</em>, }...&nbsp;<tt>]</tt></td>
    <td>Array with zero or more comma-separated CBOR objects.</td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>{}</tt></td>
    <td align="center"><tt>{</tt>&nbsp;{<em>key</em><tt>:</tt><em>value</em>, }...&nbsp;<tt>}</tt></td>
    <td>
      Map with zero or more comma-separated key/value pairs.
      Keys and values are expressed as CBOR objects.
    </td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>#6.n</tt></td>
    <td align="center"><em>n</em><tt>(</tt>&nbsp;<em>object</em>&nbsp;<tt>)</tt></td>
    <td>Tag holding a CBOR object.</td>
    <td align="center">1</td>
  </tr>
</tbody>
</table>

  <ol>
    <li>The letter <em>n</em> in the Syntax column denotes one or more digits.</li>
    <li>The optional {<em>sign</em>} must be a single hyphen (<tt>'-'</tt>) character.</li>
    <li>
      <em>Input only</em>: between the quotes, the whitespace characters
      (<tt>' '</tt>, <tt>'\t'</tt>, <tt>'\r'</tt>, <tt>'\n'</tt>)
      are <em>ignored</em>.
    </li>
    <li>
      <em>Input only</em>: the control characters
      (<tt>'\t'</tt> and <tt>'\n'</tt>)
      inside of string quotes <em>become a part of the text</em>.
      For normalizing line terminators,
      a single <tt>'\r'</tt> or the combination <tt>'\r\n'</tt>
      are rewritten as <tt>'\n'</tt>.
      To <em>avoid</em> getting newline characters (<tt>'\n'</tt>)
      included in multi-line text strings,
      a <em>line continuation marker</em> consisting of a backslash&nbsp;(<tt>'\'</tt>)
      immediately preceding the newline may be used.
    </li>
    <li>
      Text strings may also include JavaScript compatible escape sequences
      (<tt>'\''</tt>, <tt>'\"'</tt>, <tt>'\\'</tt>,
      <tt>'\b'</tt>, <tt>'\f'</tt>, <tt>'\n'</tt>,
      <tt>'\r'</tt>, <tt>'\t'</tt>, <tt>'\u</tt><em>hhhh</em><tt>'</tt>).
    </li>
    <li>
      <em>Input only</em>.
    </li>
  </ol>

      </section>

    </section>  
   
    </section>   
    
    <section anchor="IANA">
       <name>IANA Considerations</name>
      <t>This memo includes no request to IANA.</t>
    </section>
    
    <section anchor="Security">
       <name>Security Considerations</name>
      <t>All is good &#x1f638;</t>
      <t>U-CBOR does not introduce security issues beyond
      what is already applicable to  <xref target="RFC8949"/>.
      Applications may certainly add security issues, but these are
      out of scope for this specification.</t>
    </section>
    
   </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8949.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3629.xml"/>
        <reference anchor="IEEE754" target="https://ieeexplore.ieee.org/document/8766229" quoteTitle="true" derivedAnchor="IEEE754">
          <front>
            <title>IEEE Standard for Floating-Point Arithmetic</title>
            <author>
              <organization showOnFrontPage="true">IEEE</organization>
            </author>
            <date/>
          </front>
          <seriesInfo name="IEEE Std" value="754-2019"/>
          <seriesInfo name="DOI" value="10.1109/IEEESTD.2019.8766229"/>
        </reference>
      </references>
 
      <references>
        <name>Informative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9052.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9053.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8785.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"/>

        <reference anchor="CSF" target="https://cyberphone.github.io/javaapi/org/webpki/cbor/doc-files/signatures.html">
          <front>
            <title>CBOR Signature Format (CSF)</title>
            <author initials="A" surname="Rundgren">
              <organization/>
            </author>
          </front>
        </reference>

        <reference anchor="CEF" target="https://cyberphone.github.io/javaapi/org/webpki/cbor/doc-files/encryption.html">
          <front>
            <title>CBOR Encryption Format (CEF)</title>
            <author initials="A" surname="Rundgren">
              <organization/>
            </author>
          </front>
        </reference>

        <reference anchor="COTX" target="https://www.ietf.org/archive/id/draft-rundgren-cotx-04.html">
          <front>
            <title>CBOR Object Type Extension (COTX)</title>
            <author initials="A" surname="Rundgren">
              <organization/>
            </author>
          </front>
        </reference>

        <reference anchor="CONSTRAINED" target="https://github.com/cyberphone/D-CBOR/blob/main/d-cbor-4-constrained-devices.md">
          <front>
            <title>D-CBOR for Constrained Devices</title>
            <author/>
          </front>
        </reference>
 
        <reference anchor="NODE.JS" target="https://nodejs.org/">
          <front>
            <title>Node.js - JavaScript server</title>
            <author/>
          </front>
        </reference>
 
        <reference anchor="CBOR.JS" target="https://github.com/cyberphone/CBOR.js">
          <front>
            <title>CBOR.js - CBOR for JavaScript</title>
            <author/>
          </front>
        </reference>

        <reference anchor="CSF-LAB" target="https://test.webpki.org/csf-lab">
          <front>
            <title>Online CBOR and CSF test tool</title>
            <author/>
          </front>
        </reference>

        <reference anchor="PLAYGROUND" target="https://cyberphone.github.io/CBOR.js/doc/playground.html">
          <front>
            <title>Online CBOR testing tool</title>
            <author/>
          </front>
        </reference>

        <reference anchor="OPENKEYSTORE" target="https://github.com/cyberphone/openkeystore">
          <front>
            <title>Java library supporting JSON, CBOR, and Crypto</title>
            <author/>
          </front>
        </reference>

        <reference anchor="ANDROID-CBOR" target="https://github.com/cyberphone/android-cbor">
          <front>
            <title>Android/Java library supporting CBOR and Crypto</title>
            <author/>
          </front>
        </reference>

        <reference anchor="OPENAPI" target="https://openapis.org/">
          <front>
            <title>The OpenAPI Initiative</title>
            <author/>
          </front>
        </reference>

        <reference anchor="CREDENTIALS" target="https://www.w3.org/TR/vc-data-integrity/">
          <front>
            <title>Verifiable Credential Data Integrity 1.0</title>
            <author initials="M" surname="Sporny (et al)">
               <organization/>
            </author>
            <date year="2025"/>
          </front>
        </reference> 

        <reference anchor="CBOR.ME" target="https://cbor.me/">
          <front>
            <title>Online CBOR testing tool</title>
            <author initials="C" surname="Bormann">
               <organization/>
            </author>
          </front>
        </reference> 
       
        <reference anchor="ECMASCRIPT" target="https://www.ecma-international.org/publications/standards/Ecma-262.htm" quoteTitle="true" derivedAnchor="ECMA262">
          <front>
            <title>ECMAScript® 2024 Language Specification</title>
            <author>
              <organization showOnFrontPage="true">Ecma International</organization>
            </author>
            <date year="2024" month="June"/>
          </front>
          <refcontent>Standard ECMA-262, 15th Edition</refcontent>
        </reference>

        <reference anchor="GORDIAN" target="https://datatracker.ietf.org/doc/draft-mcnally-envelope/">
          <front>
            <title>The Gordian Envelope Structured Data Format</title>
            <author fullname="Wolf McNally" initials="W." surname="McNally">
              <organization>Blockchain Commons</organization>
            </author>
            <author fullname="Christopher Allen" initials="C." surname="Allen">
              <organization>Blockchain Commons</organization>
            </author>
          </front>
        </reference>

        <reference anchor="WALLET" target="https://cyberphone.github.io/doc/defensive-publications/partial-encryption-full-signature.pdf">
          <front>
            <title>Defensive publication: Partial Encryption, Full Signature</title>
            <author fullname="Anders Rundgren" initials="A." surname="Rundgren">
              <organization/>
            </author>
          </front>
        </reference>
        
      </references>
    </references>

    <section anchor="sample.values">
    <name>Deterministic Encoding Samples</name>

      <section anchor="ucbor.integers">
          <name>Integers</name>
<t>This <em>normative</em> section holds a selection
of CBOR integer values, with an emphasize on edge cases.</t>

<table>
<name>Integers</name>
<thead>
  <tr><th align="center">Value</th>
  <th align="center">CBOR Encoding</th>
  <th align="center">Description</th></tr>
</thead>
<tbody>
<tr><td align="right"><tt>0</tt></td>
<td align="right"><tt>00</tt></td>
<td>Smallest positive implicit <tt>int</tt></td></tr>
<tr><td align="right"><tt>-1</tt></td>
<td align="right"><tt>20</tt></td>
<td>Smallest negative implicit <tt>int</tt></td></tr>
<tr><td align="right"><tt>23</tt></td>
<td align="right"><tt>17</tt></td>
<td>Largest positive implicit <tt>int</tt></td></tr>
<tr><td align="right"><tt>-24</tt></td>
<td align="right"><tt>37</tt></td>
<td>Largest negative implicit <tt>int</tt></td></tr>
<tr><td align="right"><tt>24</tt></td>
<td align="right"><tt>1818</tt></td>
<td>Smallest positive one-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-25</tt></td>
<td align="right"><tt>3818</tt></td>
<td>Smallest negative one-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>255</tt></td>
<td align="right"><tt>18ff</tt></td>
<td>Largest positive one-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-256</tt></td>
<td align="right"><tt>38ff</tt></td>
<td>Largest negative one-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>256</tt></td>
<td align="right"><tt>190100</tt></td>
<td>Smallest positive two-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-257</tt></td>
<td align="right"><tt>390100</tt></td>
<td>Smallest negative two-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>65535</tt></td>
<td align="right"><tt>19ffff</tt></td>
<td>Largest positive two-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-65536</tt></td>
<td align="right"><tt>39ffff</tt></td>
<td>Largest negative two-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>65536</tt></td>
<td align="right"><tt>1a00010000</tt></td>
<td>Smallest positive four-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-65537</tt></td>
<td align="right"><tt>3a00010000</tt></td>
<td>Smallest negative four-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>4294967295</tt></td>
<td align="right"><tt>1affffffff</tt></td>
<td>Largest positive four-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-4294967296</tt></td>
<td align="right"><tt>3affffffff</tt></td>
<td>Largest negative four-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>4294967296</tt></td>
<td align="right"><tt>1b0000000100000000</tt></td>
<td>Smallest positive eight-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-4294967297</tt></td>
<td align="right"><tt>3b0000000100000000</tt></td>
<td>Smallest negative eight-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>18446744073709551615</tt></td>
<td align="right"><tt>1bffffffffffffffff</tt></td>
<td>Largest positive eight-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>-18446744073709551616</tt></td>
<td align="right"><tt>3bffffffffffffffff</tt></td>
<td>Largest negative eight-byte <tt>int</tt></td></tr>
<tr><td align="right"><tt>18446744073709551616</tt></td>
<td align="right"><tt>c249010000000000000000</tt></td>
<td>Smallest positive <tt>bigint</tt></td></tr>
<tr><td align="right"><tt>-18446744073709551617</tt></td>
<td align="right"><tt>c349010000000000000000</tt></td>
<td>Smallest negative <tt>bigint</tt></td></tr>
</tbody>
</table>
      </section>

      <section anchor="ucbor.floats">
        <name>Floating Point Numbers</name>
<t>This <em>normative</em> section holds a selection
of <xref target="IEEE754"/> 16, 32, and 64-bit values,
with an emphasize on edge cases.</t>
<t>The textual representation of the values is based on
the serialization method for the <tt>Number</tt> data type,
defined by <xref target="ECMASCRIPT"/> with one change:
to comply with diagnostic notation
(section 8 of <xref target="RFC8949"/>), all values are
expressed as floating-point numbers.
The rationale for using <xref target="ECMASCRIPT"/> serialization is
because it supposed to generate the shortest and most
correct representation of <xref target="IEEE754"/> numbers.</t>

<table>
<name>Floating Point Numbers</name>
<thead>
  <tr><th align="center">Value</th>
  <th align="center">CBOR Encoding</th>
  <th align="center">Description</th></tr>
</thead>
<tbody>
<tr><td align="right"><tt>0.0</tt></td>
<td align="right"><tt>f90000</tt></td>
<td>Zero</td></tr>
<tr><td align="right"><tt>-0.0</tt></td>
<td align="right"><tt>f98000</tt></td>
<td>Negative zero</td></tr>
<tr><td align="right"><tt>Infinity</tt></td>
<td align="right"><tt>f97c00</tt></td>
<td>Infinity</td></tr>
<tr><td align="right"><tt>-Infinity</tt></td>
<td align="right"><tt>f9fc00</tt></td>
<td>-Infinity</td></tr>
<tr><td align="right"><tt>NaN</tt></td>
<td align="right"><tt>f97e00</tt></td>
<td>NaN</td></tr>
<tr><td align="right"><tt>5.960464477539063e-8</tt></td>
<td align="right"><tt>f90001</tt></td>
<td>Smallest positive <em>subnormal</em> 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>0.00006097555160522461</tt></td>
<td align="right"><tt>f903ff</tt></td>
<td>Largest positive <em>subnormal</em> 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>0.00006103515625</tt></td>
<td align="right"><tt>f90400</tt></td>
<td>Smallest positive 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>65504.0</tt></td>
<td align="right"><tt>f97bff</tt></td>
<td>Largest positive 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.401298464324817e-45</tt></td>
<td align="right"><tt>fa00000001</tt></td>
<td>Smallest positive <em>subnormal</em> 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.1754942106924411e-38</tt></td>
<td align="right"><tt>fa007fffff</tt></td>
<td>Largest positive <em>subnormal</em> 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.1754943508222875e-38</tt></td>
<td align="right"><tt>fa00800000</tt></td>
<td>Smallest positive 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>3.4028234663852886e+38</tt></td>
<td align="right"><tt>fa7f7fffff</tt></td>
<td>Largest positive 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>5.0e-324</tt></td>
<td align="right"><tt>fb0000000000000001</tt></td>
<td>Smallest positive <em>subnormal</em> 64-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>2.225073858507201e-308</tt></td>
<td align="right"><tt>fb000fffffffffffff</tt></td>
<td>Largest positive <em>subnormal</em> 64-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>2.2250738585072014e-308</tt></td>
<td align="right"><tt>fb0010000000000000</tt></td>
<td>Smallest positive 64-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.7976931348623157e+308</tt></td>
<td align="right"><tt>fb7fefffffffffffff</tt></td>
<td>Largest positive 64-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>-0.0000033333333333333333</tt></td>
<td align="right"><tt>fbbecbf647612f3696</tt></td>
<td>Randomly selected number</td></tr>
<tr><td align="right"><tt>10.559998512268066</tt></td>
<td align="right"><tt>fa4128f5c1</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>10.559998512268068</tt></td>
<td align="right"><tt>fb40251eb820000001</tt></td>
<td>Next in succession</td></tr>
<tr><td align="right"><tt>295147905179352830000.0</tt></td>
<td align="right"><tt>fa61800000</tt></td>
<td><tt>2<sup>68</sup></tt> (diagnostic notation truncates precision)</td></tr>
<tr><td align="right"><tt>2.0</tt></td>
<td align="right"><tt>f94000</tt></td>
<td>Number without a fractional part</td></tr>
<tr><td align="right"><tt>-5.960464477539063e-8</tt></td>
<td align="right"><tt>f98001</tt></td>
<td>Smallest negative <em>subnormal</em> 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>-5.960464477539062e-8</tt></td>
<td align="right"><tt>fbbe6fffffffffffff</tt></td>
<td>Adjacent smallest negative <em>subnormal</em> 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>-5.960464477539064e-8</tt></td>
<td align="right"><tt>fbbe70000000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>-5.960465188081798e-8</tt></td>
<td align="right"><tt>fab3800001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>0.0000609755516052246</tt></td>
<td align="right"><tt>fb3f0ff7ffffffffff</tt></td>
<td>Adjacent largest <em>subnormal</em> 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>0.000060975551605224616</tt></td>
<td align="right"><tt>fb3f0ff80000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>0.000060975555243203416</tt></td>
<td align="right"><tt>fa387fc001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>0.00006103515624999999</tt></td>
<td align="right"><tt>fb3f0fffffffffffff</tt></td>
<td>Adjacent smallest 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>0.00006103515625000001</tt></td>
<td align="right"><tt>fb3f10000000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>0.00006103516352595761</tt></td>
<td align="right"><tt>fa38800001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>65503.99999999999</tt></td>
<td align="right"><tt>fb40effbffffffffff</tt></td>
<td>Adjacent largest 16-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>65504.00000000001</tt></td>
<td align="right"><tt>fb40effc0000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>65504.00390625</tt></td>
<td align="right"><tt>fa477fe001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>1.4012984643248169e-45</tt></td>
<td align="right"><tt>fb369fffffffffffff</tt></td>
<td>Adjacent smallest <em>subnormal</em> 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.4012984643248174e-45</tt></td>
<td align="right"><tt>fb36a0000000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>1.175494210692441e-38</tt></td>
<td align="right"><tt>fb380fffffbfffffff</tt></td>
<td>Adjacent largest <em>subnormal</em> 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.1754942106924412e-38</tt></td>
<td align="right"><tt>fb380fffffc0000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>1.1754943508222874e-38</tt></td>
<td align="right"><tt>fb380fffffffffffff</tt></td>
<td>Adjacent smallest 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>1.1754943508222878e-38</tt></td>
<td align="right"><tt>fb3810000000000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
<tr><td align="right"><tt>3.4028234663852882e+38</tt></td>
<td align="right"><tt>fb47efffffdfffffff</tt></td>
<td>Adjacent largest 32-bit <tt>float</tt></td></tr>
<tr><td align="right"><tt>3.402823466385289e+38</tt></td>
<td align="right"><tt>fb47efffffe0000001</tt></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""</td></tr>
</tbody>
</table>

    </section>

    <section anchor="ucbor.invalid">
      <name>Invalid Encodings</name>
      <t>The following table holds a selection of valid CBOR objects,
      not permitted by U-CBOR.</t>
<table>
<name>Invalid Encodings</name>
<thead>
  <tr><th align="center">CBOR Encoding</th><th align="center">Diagnostic Notation</th>
  <th align="center">Description</th><th align="center">Note</th></tr>
</thead>
<tbody>
<tr>
<td><tt>a2616200616101</tt></td>
<td><tt>{"b":0,"a":1}</tt></td>
<td>Improper map key ordering</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>1900ff</tt></td>
<td><tt>255</tt></td>
<td>Number with leading zero bytes</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>c34a00010000000000000000</tt></td>
<td><tt>-18446744073709551617</tt></td>
<td>Number with leading zero bytes</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>Fa41280000</tt></td>
<td><tt>10.5</tt></td>
<td>Not in shortest encoding</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>fa7fc00000</tt></td>
<td><tt>NaN</tt></td>
<td>Not in shortest encoding</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>c243010000</tt></td>
<td><tt>65536</tt></td>
<td>Incorrect value for <tt>bigint</tt></td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>f97e01</tt></td>
<td><tt>NaN</tt></td>
<td>NaN with payload</td>
<td align="center">1</td>
</tr>

<tr>
<td><tt>f7</tt></td>
<td><tt>undefined</tt></td>
<td>Unsupported simple type</td>
<td></td>
</tr>

<tr>
<td><tt>f0</tt></td>
<td><tt>simple(16)</tt></td>
<td>Unsupported simple type</td>
<td></td>
</tr>

<tr>
<td><tt>5f4101420203ff</tt></td>
<td><tt>(_ h'01', h'0203')</tt></td>
<td>Unsupported indefinite length object</td>
<td></td>
</tr>

</tbody>
</table>
<ol>
<li>See also <xref target="legacy.systems"/>.</li>
</ol>

    </section>

    </section>
    
    <section anchor="enveloped.signatures">
      <name>Enveloped Signatures</name>
      <t>This is a <em>non-normative</em> appendix showing how U-CBOR
      can be used for supporting enveloped signatures.</t>
      <t>The primary advantages with <em>enveloped</em> signatures compared to
      <em>enveloping</em> signatures (like used by COSE <xref target="RFC9052"/>), 
      include:</t>
      <ul>
        <li>Keeping the <em>structure</em> of the original (unsigned) data intact,
        by simply making signatures an additional attribute.</li>
        <li>
        <t>
        Enabling top-level, <em>object identifiers</em> 
        to become a part of the signed data as well:</t>
               <sourcecode name="Tag object-id" type="cbor">
<![CDATA[123456789({                            # CBOR tag (objectId)
  1: "This is not rocket science!",    # Object instance data
  2: [38.8882, -77.01988],             #         ""
  3: «signature covering the entire object»
})]]></sourcecode>
<t>
See also <xref target="COTX"/>.
</t>
        </li>
        <li>Permitting signing CBOR data and associated security
        attributes (aka "headers"), <em>in one go</em>, without
        having to wrap data in CBOR "bstr" objects.
        Non-wrapped data also makes debugging and documentation easier.</li>
      </ul>
      <t>Enveloped signatures are for example featured in Verified Credentials 
      <xref target="CREDENTIALS"/>.
      A drawback with designs based on JSON <xref target="RFC8259"/> is that they
      rely on <em>canonicalization schemes</em> like JCS <xref target="RFC8785"/>,
      that require specialized encoders and decoders, whereas U-CBOR works
      "straight out of the box".</t>

      <section anchor="example.signature">
      <name>Sample Signature</name>
      <t>Although this specification is not "married" to any particular
      signature schema, the following example uses the CBOR Signature Format
      <xref target="CSF"/>.
      For the sake of simplicity, the example uses an HMAC
      (see <xref target="example.parameters"/>)
      as signature algorithm.</t>
      <t>For a more sophisticated use of U-CBOR, combining
      signatures and encryption, see <xref target="WALLET"/>.</t>

      <section anchor="example.unsigned">
        <name>Unsigned Data</name>
        <t>Imagine you have a CBOR map object like the following
        that you want to sign:</t>
       <sourcecode name="Unsigned Data" type="cbor">
<![CDATA[{
  1: "data",
  2: "more data"
}]]></sourcecode>
      </section>
      <section anchor="example.signing">
        <name>Signature Process</name>
        <t>This section describes the steps required for adding an
        enveloped signature to the CBOR map object in
        <xref target="example.unsigned"/>.
        To avoid confusing CBOR <tt>map</tt> keys with cryptographic keys,
        the former are referred to as "labels".
        </t>
        <ol>
        <li>Add an empty CSF container (a CBOR map) to the unsigned CBOR map
        using an <em>application-defined</em> label (-1).</li>
        <li>Add the designated signature algorithm to the
        CSF container using the CSF algorithm label (1).</li>
        <li><em>Optional</em>. Add other signature meta data to the
        CSF container. Not used in the example.</li>
        <li><t>Generate a signature by invoking a (hypothetical)
        signature method with the following arguments:</t>
          <ul>
          <li>the designated signature key.</li>
          <li>the designated signature algorithm.</li>
          <li>the <em>deterministic encoding</em> of the
          current CBOR object in its <em>entirety</em>.
          In the example that would be 
          <tt>a301646461746102696d6f7265206461746120a10105</tt>,
          if expressed in hex code.</li>
          </ul>
        </li>
        <li>Add the returned signature value to the CSF container
        using the CSF signature label (6).</li>
        </ol>
        <t>The result after the final step (using the parameters 
        from <xref target="example.parameters"/>), should
        match the following CBOR object:</t>
<sourcecode name="Unsigned Data" type="cbor">
<![CDATA[{
  1: "data",
  2: "more data",
  -1: {
    1: 5,
    6: h'4853d7730cc1340682b1748dc346cf627a5e91ce62c67fff15c40257ed2a37a1'
  }
}]]></sourcecode>
      <t>Note that the signature covers the <em>entire</em> CBOR object except for
      the CSF signature value and label (6).</t>
      </section>

      <section anchor="example.validation">
        <name>Validation Process</name>
        <t>In order to validate the enveloped signature created in the
        <xref target="example.signing"/>,
        the following steps are performed:</t>
        <ol>
        <li><t>Fetch a <em>reference</em> to the CSF container using the
        <em>application-defined</em> label (-1).
        Next perform the following operations using the reference:</t>
        <ol>
          <li>Retrieve the signature algorithm using the CSF algorithm label (1).</li>
          <li>Retrieve the signature value using the CSF algorithm label (6).</li>
          <li>Remove the CSF algorithm label (6) and its associated value.</li>
        </ol>
        <t>Now we should have exactly the same CBOR object as we had <em>before</em>
        step #4 in <xref target="example.signing"/>.
        That is:</t>
<sourcecode name="Unsigned Data" type="cbor">
<![CDATA[{
  1: "data",
  2: "more data",
  -1: {
    1: 5
  }
}]]></sourcecode>
        </li>
        <li><t>Validate the signature data by invoking a (hypothetical)
        signature validation method with the following arguments:</t>
          <ul>
          <li>the designated signature key
          (in the example taken from <xref target="example.parameters"/>).</li>
          <li>the signature algorithm retrieved in step #1.</li>
          <li>the signature value retrieved in step #1.</li>
          <li>the <em>deterministic encoding</em> of the
          current CBOR object in its <em>entirety</em>.</li>
          </ul>
        </li>
        </ol>
        <t>Note: this is a "bare-bones" validation process, lacking the ruggedness
        of a real-world implementation.</t>
      </section>

      <section anchor="example.parameters">
        <name>Example Parameters</name>
        <t>The signature and validation processes depend on the
        COSE <xref target="RFC9053"/> algorithm "HMAC&nbsp;256/256" and an
        associated 256-bit key, here provided in hex code:</t>
        <sourcecode name="Key" type="any">
<![CDATA[7fdd851a3b9d2dafc5f0d00030e22b9343900cd42ede4948568a4a2ee655291a]]></sourcecode>
      </section>

      </section>

      <section anchor="example.code">
        <name>Code Example</name>
        <t>Using a JavaScript implementation <xref target="CBOR.JS"/>
        of U-CBOR, together with Node.js
        <xref target="NODE.JS"/>,
        basic signature creation and validation supporting
        the example in  <xref target="example.signature"/>,
        could be performed by the following code:</t>
        <sourcecode name="code.with.node.js" type="javascript">
<![CDATA[// hmac.mjs
import CBOR from 'cbor-object';
const crypto = await import('node:crypto');

// CSF constants
const CSF_ALG_LBL = CBOR.Int(1);
const CSF_SIG_LBL = CBOR.Int(6);

// COSE => Node.js algorithm translation
const HASH_ALGORITHMS = new Map()
    .set(5, "sha256").set(6, "sha384").set(7, "sha512");

function hmac(coseAlg, key, data) {
    let alg = HASH_ALGORITHMS.get(coseAlg);
    if (alg === undefined) throw "Unknown alg: " + coseAlg;
    return crypto.createHmac(alg, key).update(data).digest();
}

const SHARED_KEY = crypto.createSecretKey(
    '7fdd851a3b9d2dafc5f0d00030e22b9343900cd42ede4948568a4a2ee655291a', 'hex');

const APP_P1_LBL  = CBOR.Int(1);                   // Application label
const APP_P2_LBL  = CBOR.Int(2);                   //        ""
const APP_CSF_LBL = CBOR.Int(-1);                  // Where to put the
                                                   // CSF container
////////////////////////////////////
// Create an unsigned CBOR object //
////////////////////////////////////
let object = CBOR.Map()
    .set(APP_P1_LBL, CBOR.String("data"))          // Application data
    .set(APP_P2_LBL, CBOR.String("more data"));    //        ""

////////////////////////////////////////
// Add a signature to the CBOR object //
////////////////////////////////////////
const COSE_ALG = 5;                                // Selected HMAC algorithm

let csf = CBOR.Map()                               // Create CSF container and
    .set(CSF_ALG_LBL, CBOR.Int(COSE_ALG));         // add COSE algorithm to it
object.set(APP_CSF_LBL, csf);                      // Add CSF container to object
let sig = hmac(COSE_ALG,                           // Generate signature over
               SHARED_KEY,                         // the current object
               object.encode());                   // encode(): all we got so far
csf.set(CSF_SIG_LBL, CBOR.Bytes(sig));             // Add signature to CSF container
let cborBinary = object.encode();                  // Return CBOR as an Uint8Array
        
console.log(object.toString());                    // Show in Diagnostic Notation

/////////////////////////////////////
// Validate the signed CBOR object //
/////////////////////////////////////
object = CBOR.decode(cborBinary);                  // Decode CBOR object
csf = object.get(APP_CSF_LBL);                     // Get CSF container
let alg = csf.get(CSF_ALG_LBL).getInt();           // Get COSE algorithm
let readSig = csf.remove(CSF_SIG_LBL).getBytes();  // Get and REMOVE signature value
let actualSig = hmac(alg,                          // Calculate signature over
                     SHARED_KEY,                   // the current object
                     object.encode());             // encode(): all but the signature
if (CBOR.compareArrays(readSig, actualSig)) {      // HMAC validation
    throw "Signature did not validate";
}
// Validated object, access the "payload":
let p1 = object.get(APP_P1_LBL).getString();       // p1 should now contain "data"]]></sourcecode>
<t>
Note that this code depends heavily on the CBOR tool features
outlined in <xref target="ucbor.tools"/>.
</t>
      </section>

    </section>

    <section anchor="legacy.systems">
      <name>Supporting Existing Systems</name>
      <t>
It is assumed that <em>most</em>
systems using CBOR are able to process an (<em>application specific</em>), 
selection of CBOR data items that are encoded in compliance with
<xref target="RFC8949"/>.  Since the deterministic encoding scheme
mandated by U-CBOR, also is compliant with <xref target="RFC8949"/>,
there should be no major interoperability issues. 
That is, if the previous assumption actually is correct &#x1f60f;
</t>
<t>
However, in the <em>other</em> direction (U-CBOR tools processing
data from Systems using "legacy" CBOR encoding schemes),
the situation is likely to be considerably more challenging
since deterministic encoding "by design" is <em>strict</em>.
Due to this potential obstacle, implementers of U-CBOR tools,
are RECOMMENDED to offer <em>decoder</em> options that permit "relaxing"
the rigidness of deterministic encoding with respect to:</t>
<dl newline="true">
<dt>Numbers:</dt>
<dd>Numbers MUST still be compliant with <xref target="RFC8949"/>.</dd>
<dt>Sorted maps:</dt>
<dd>Duplicate keys MUST still be rejected.</dd>
</dl>
<t>Note that regardless of the format of decoded CBOR data, a compliant
U-CBOR implementation MUST maintain deterministic encoding.
See also <xref target="ucbor.invalid"/>.</t>
    </section>

    <section anchor="tools.online">
      <name>Compatible Online Tools</name>
      <t>For testing and learning about U-CBOR,
      there are currently a number of compatible
      online tools (subject to availability...).</t>
      <dl newline="true">
        <dt><xref target="PLAYGROUND"/>:</dt>
        <dd>Browser-based CBOR "playground" </dd>
        <dt><xref target="CSF-LAB"/>:</dt>
        <dd>Server-based CBOR and <xref target="CSF"/> test system</dd>
      </dl>
    </section>

    <section anchor="tools.implementations">
      <name>Compatible Implementations</name>
      <t>For using U-CBOR in applications, there are
      currently a number of compatible libraries.</t>
      <dl newline="true">
        <dt><xref target="CBOR.JS"/>:</dt>
        <dd>JavaScript-based implementation supporting
        browsers as well as <xref target="NODE.JS"/></dd>
        <dt><xref target="OPENKEYSTORE"/>:</dt>
        <dd>Java-based implementation that also 
        supports <xref target="CSF"/> and <xref target="CEF"/></dd>
        <dt><xref target="ANDROID-CBOR"/>:</dt>
        <dd>Android Java-based implementation that also 
        supports <xref target="CSF"/> and <xref target="CEF"/></dd>
      </dl>
    </section>

    <section anchor="DocHistory" numbered="false">
      <name>Document History</name>
      <ul>
        <li>00. First cut.</li>
        <li>01. Editorial.  Changed order of columns in invalid encoding.</li>
        <li>02. Editorial.  "unwrapped" changed to "non-wrapped".</li>
        <li>
        <t>03:</t>
        <t>Tweaking the abstract.</t>
        <t>Protocol Primitives Support sub-section added.</t>
        <t>Diagnostic Notation Support sub-section added.</t>
        <t>Updated CBOR Tool Requirements</t>
        <t>Updated code example to actually use crypto</t>
        <t>Updated Acknowledgements.</t>
        <t>Updated Security Considerations.</t>
        </li>
                <li>
        <t>04:</t>
        <t>Minor addition in CBOR tools</t>
        <t>Updated Acknowledgements</t>
        </li>
      </ul>
    </section>

    <section anchor="Acknowledgements" numbered="false">
      <name>Acknowledgements</name>
      <t>For verifying the correctness of the encoding scheme, the <xref target="CBOR.ME"/> 
      on-line CBOR tool, by the <xref target="RFC8949"/> author,
      Carsten Bormann, proved to be invaluable.</t>
    </section>
    
 </back>
</rfc>
