<?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;">
]>

<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="info"
  docName="draft-rundgren-universal-cbor-01"
  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-01"/>
   
    <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.
To foster interoperability, deterministic encoding
is mandated.  Furthermore, the document outlines how
deterministic encoding combined with enhanced CBOR tools,
enables the support of cryptographic constructs that
operate on "raw" (unwrapped) CBOR data.  The intended
audience for this document are 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" format="default"/>.
        </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 has proved to be
deployable in constrained environments, the primary target is rather
mainstream 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" (unwrapped)
CBOR data, compliant U-CBOR tools need additional functionality.
See also <xref target="enveloped.signatures" format="default"/>.
        </t>
        <t>
<xref target="detailed.description" format="default"/> 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 section 8 of <xref 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>
        <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">Note</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>
      </section>
      
      <section>
        <name>Deterministic Encoding Scheme</name>
        <t>
The U-CBOR encoding scheme adheres to section 4.2 of <xref target="RFC8949"/>,
but adds a few constraints (denoted by RFC+), where the RFC offers choices.
The deterministic encoding rules are as follows:
        </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 section 4.2.2 of <xref 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="sample.integers" format="default"/>
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="sample.floats" format="default"/>
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 encoding according to this specification
maintains type and data uniqueness, there are no specific restrictions or
tests needed in order to determine map key equivalence.
As an example, the floating-point numbers <tt>0.0</tt> and
<tt>-0.0</tt>, and the integer number <tt>0</tt>
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 <xref target="RFC9052"/> (Section 2), 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" format="default"/> 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>
  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
  received and decoded CBOR data.  Note: CBOR primitives MUST remain <em>immutable</em>.
  </li>
  <li>
  It MUST be possible to <em>reserialize</em> received CBOR data,
  be it updated or not.
  </li>
  <li>
  Irrespective of if CBOR data was received, 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="sample.invalid"/>.
  </li>
</ul>
<t>
It is RECOMMENDED <em>separating</em> CBOR data and 
application / platform-level data,
since the latter may not always <em>reserialize</em> as expected,
like in this Chrome browser console example:
</t>
<sourcecode name="Platform issues" type="cbor">
<![CDATA[> let date = new Date('2025-03-02T13:08:55.0001Z');
> date.toISOString()
'2025-03-02T13: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 a usable method.
Similar approaches are used by most ASN.1 tools.
The code in <xref target="example.code" format="default"/> shows an example
that <em>updates</em> and <em>reserializes</em> decoded CBOR data.
</t>
      </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>
    </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="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="ECMASCRIPT" target="https://www.ecma-international.org/publications/standards/Ecma-262.htm" quoteTitle="true" derivedAnchor="ECMA262">
          <front>
            <title>ECMAScript 2020 Language Specification</title>
            <author>
              <organization showOnFrontPage="true">Ecma International</organization>
            </author>
            <date year="2020" month="June"/>
          </front>
          <refcontent>Standard ECMA-262, 11th Edition</refcontent>
        </reference>

        <reference anchor="GordianEnvelope" 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>
        
      </references>
    </references>

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

      <section anchor="sample.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">Note</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="sample.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">Note</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>295147905179352830000.0</tt></td>
<td align="right"><tt>fa61800000</tt></td>
<td><tt>~2<sup>68</sup></tt></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>Close to 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>Close to 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>Close to 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>Close to 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>Close to 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>Close to 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>Close to 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>Close to 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="sample.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">Note</th></tr>
</thead>
<tbody>
<!--
<tr><td><tt>hjjh</tt></td>
<td><tt>enc</tt></td>
<td>tjoho</td></tr>
-->
<tr>
<td><tt>a2616200616101</tt></td>
<td><tt>{"b":0,"a":1}</tt></td>
<td>Improper map key ordering [1]</td>
</tr>

<tr>
<td><tt>1900ff</tt></td>
<td><tt>255</tt></td>
<td>Number with leading zero bytes [1]</td>
</tr>

<tr>
<td><tt>c34a00010000000000000000</tt></td>
<td><tt>-18446744073709551617</tt></td>
<td>Number with leading zero bytes [1]</td>
</tr>

<tr>
<td><tt>Fa41280000</tt></td>
<td><tt>10.5</tt></td>
<td>Not in shortest encoding [1]</td>
</tr>

<tr>
<td><tt>fa7fc00000</tt></td>
<td><tt>NaN</tt></td>
<td>Not in shortest encoding [1]</td>
</tr>

<tr>
<td><tt>c243010000</tt></td>
<td><tt>65536</tt></td>
<td>Incorrect value for <tt>bigint</tt> [1]</td>
</tr>

<tr>
<td><tt>f97e01</tt></td>
<td><tt>NaN</tt></td>
<td>NaN with payload [1]</td>
</tr>

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

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

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

</tbody>
</table>
<ol>
<li>See also <xref target="legacy.systems" format="default"/>.</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 enveloped signatures compared to
      the approach 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>Permitting signing CBOR data and associated security
        attributes (aka "headers"), <em>in one go</em>, without
        having to wrap data in CBOR "bstr" objects.</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>
      <t>Although this specification is not "married" to any particular
      signature schema, the example uses the CBOR Signature Format
      <xref target="CSF"/>.
      For the sake of simplicity, the example uses an HMAC
      (see <xref target="example.parameters" format="default"/>)
      as signature algorithm.</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>
      <t>Then continue to the next section 
      (<xref target="example.signing" format="default"/>)...</t>
      </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" format="default"/>.
        </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" format="default"/>), 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" format="default"/>,
        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" format="default"/>.
        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" format="default"/>).</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 anchor="example.code">
        <name>Code Example</name>
        <t>Using the JavaScript implementation mentioned in
        <xref target="tools.implementations" format="default"/>,
        basic signature validation of the signed CBOR object created
        in  <xref target="example.signing" format="default"/>,
        could be performed by the following code:</t>
        <sourcecode name="Validation Code" type="any">
<![CDATA[// The variable cborBinary is supposed to contain CBOR
let object = CBOR.decode(cborBinary);             // Decode
let csf = object.get(CBOR.Int(-1));               // Get CSF container
let alg = csf.get(CBOR.Int(1)).getInt();          // Read algorithm
let sig = csf.remove(CBOR.Int(6)).getBytes();     // Read and remove signature value
let key = CBOR.fromHex('7fdd851a3b9d2dafc5f0d00030e22b9343900cd42ede4948568a4a2ee655291a');

// Hypothetical HMAC validation method:
hmacValidate(alg, sig, key, object.encode());     // Note that object.encode()
                                                  // reserializes all but sig.
// Validated object, access the "payload":
let param = object.get(CBOR.Int(1)).getString();  // Now param should contain "data"]]></sourcecode>
<t>
Note that this code depends heavily on the CBOR tool features
outlined in <xref target="ucbor.tools" format="default"/>.
</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>
<ul>
<li>Numbers.  Numbers MUST still be compliant with <xref target="RFC8949"/>.</li>
<li>Sorted maps.  Duplicate keys MUST still be rejected.</li>
</ul>
<t>Note that regardless of the format of received CBOR data, a compliant
U-CBOR implementation MUST maintain deterministic encoding.</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>Browser-based CBOR "playground":</dt>
        <dd>https://cyberphone.github.io/CBOR.js/doc/playground.html</dd>
        <dt>Server-based CBOR and <xref target="CSF"/> test system:</dt>
        <dd>https://test.webpki.org/csf-lab</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 ibraries.</t>
      <dl newline="true">
        <dt>JavaScript-based implementation:</dt>
        <dd>https://github.com/cyberphone/CBOR.js</dd>
        <dt>Java-based implementation that also 
        supports <xref target="CSF"/> and <xref target="CEF"/>:</dt>
        <dd>https://github.com/cyberphone/openkeystore</dd>
        <dt>Android Java-based implementation that also 
        supports <xref target="CSF"/> and <xref target="CEF"/>:</dt>
        <dd>https://github.com/cyberphone/android-cbor</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>
      </ul>
    </section>

    <section anchor="Acknowledgements" numbered="false">
      <name>Acknowledgements</name>
      <t>This work was inspired by a CBOR based project known as
      <xref target="GordianEnvelope"/>, pioneered by Wolf McNally and Christopher Allen.
      This project also exploits the ability to hash "raw" (unwrapped) CBOR data, enabled by the use of a deterministic encoding scheme.</t>
    </section>
    
 </back>
</rfc>
