<?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-cbor-core-06"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3">

  <front>
    <title abbrev="CBOR/c">CBOR&nbsp;Core (CBOR/c)</title>

    <seriesInfo name="Internet-Draft" value="draft-rundgren-cbor-core-06"/>
   
    <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>Embedded</keyword>
    <keyword>Signature</keyword>

    <abstract>
      <t>
This document defines CBOR&nbsp;Core (CBOR/c),
a profile 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 CBOR&nbsp;Core (CBOR/c) 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, CBOR/c 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
systems using CBOR.
See also <xref target="legacy.systems"/>.
        </t>
    <t>
CBOR/c is intended to be agnostic with respect to programming
languages and platforms.
        </t>
        <t>
By combining the compact binary representation and the rich set of
data types offered by CBOR, with a deterministic encoding scheme,
CBOR/c could for <em>new designs</em>, serve as a 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 CBOR/c tools need additional functionality.
See also <xref target="embedded.signatures"/>.
        </t>
        <section anchor="design.goals">
        <name>Design Goals</name>
        <t>
The primary goal with this specification, is providing a foundation
for CBOR tools that enable application developers to use CBOR without requiring
insights in low-level details like encoding.  In most cases, it should be sufficient
to consult a list of supported data types.  See also <xref target="protocol.primitives"/>.
        </t>
        <t>
<xref target="detailed.description"/> contains the
actual specification.
        </t>
        </section>

      
      <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 "CBOR&nbsp;Core" is in this document abbreviated to "CBOR/c".</li>
</ul>
      </section>

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

      <section anchor="core.objects">
        <name>Supported CBOR Objects</name>
        <t>The following table shows the set of CBOR objects supported by CBOR/c:</t>
<table align="left">
<name>Supported CBOR Objects</name>
<thead>
  <tr><th align="center">CBOR</th>
  <th align="center">Comment</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>
<tr><td align="center"><tt>#7.nnn</tt></td><td>Simple values</td></tr>
</tbody>
</table>
        <t>
Conforming implementations (of course) only have to implement the CBOR/c types
required by the targeted application(s).
        </t>
        <t>
Although extensions are imaginable, extensions will most likely cause
<em>interoperability issues</em> and are thus NOT&nbsp;RECOMMENDED.
  </t>
  <t>
However, nothing prevents developers from at the application (API) level, 
through CBOR tags and similar 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 that defines
data types through mapping.
</t>

      </section>
      
      <section anchor="core.encoding">
        <name>Deterministic Encoding Scheme</name>
        <t>
In CBOR/c 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 CBOR/c 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="core.integers"/>
features a list of integer sample values and their expected encoding.
        </t>
        </li>
        <li>
RFC: Floating-point numbers MUST always use the shortest
<xref target="IEEE754"/> variant that
preserves the precision of the original value.
<xref target="core.floats"/>
features a list of floating-point sample values and their expected encoding.
        </li>
        <li>
RFC+: <tt>NaN</tt> values with payloads (like <tt>f97e01</tt>),
or having the most significant bit set ("signaling"),
MUST be <em>rejected</em>.  See also <xref target="core.floats"/>.
        </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="core.tools">
        <name>CBOR Tool Requirements</name>
<t>
An important 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="embedded.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 is 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="core.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');
console.log(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.
If applied to the date example above, you would get something like following,
here using <xref target="CBOR.JS"/>:</t>
<sourcecode name="Date example" type="cbor">
<![CDATA[// "2025-03-02T13:08:55.0001+03:00"
let cbor = CBOR.fromHex("781e323032352d30332d30325431333a30383a35352e303030312b30333a3030");
let cborObject = CBOR.decode(cbor)
console.log(cborObject.getDateTime());  // JavaScript Date only supports milliseconds
                                        // and converts time to local time or UTC
> Sun Mar 02 2025 11:08:55 GMT+0100 (Central European Standard Time)
console.log(CBOR.toHex(cborObject.encode()));  // Reencode returns identical CBOR data 
> 781e323032352d30332d30325431333a30383a35352e303030312b30333a3030]]>
</sourcecode>
<t>
<xref target="example.code"/> shows an example
that <em>updates</em> and <em>reserializes</em> decoded CBOR data.
</t>

        <section anchor="protocol.primitives">
        <name>Protocol Primitives</name>
        <t>
To facilitate cross-platform <em>protocol interoperability</em>,
implementers of CBOR/c compatible tools SHOULD include <em>decoder</em>
API support for the following primitives:
        </t>
<table align="left">
<name>Protocol Primitives</name>
<thead>
  <tr>
  <th align="center">CBOR</th>
  <th align="center">Primitive</th>
  <th align="center">Comment</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>integer</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"><tt>#7.nnn</tt></td>
<td align="center"><tt>Simple</tt></td>
<td>Simple values</td>
<td align="center">5</td>
</tr>
<tr>
<td align="center"><tt>tstr</tt></td>
<td align="center"><tt>String</tt></td>
<td>Text string</td>
<td></td>
</tr>
<tr>
<td align="center"><tt>bstr</tt></td>
<td align="center"><tt>Bytes</tt></td>
<td>Byte string</td>
<td></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">6</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">6</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="core.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>
Simple values include the ranges <tt>0-23</tt> and <tt>32-255</tt>.
Note that <tt>bool</tt> and <tt>null</tt> actually are simple values.
</t>
</li>
<li>
<t>
Since CBOR lacks 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 CBOR 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="media.tyoe">
<name>Media Type</name>
<t>Protocols building on CBOR/c, are RECOMMENDED using the media type: <tt>application/cbor</tt>.</t> 
</section>

<section anchor="diagnostic.notation">
<name>Diagnostic Notation</name>
<t>Compliant CBOR/c implementations SHOULD include support for
<em>bi-directional</em> diagnostic notation, to facilitate:</t>
<ul>
<li>Generation of developer-friendly debugging and logging data</li>
<li>Easy creation of test and configuration data</li>
</ul>
<t>
Note that decoders for diagnostic notation, MUST always produce
deterministically encoded CBOR data, compliant with this specification.
This includes <em>automatic</em> sorting of map keys as well.
</t>
<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 align="left">
<name>Diagnostic Notation</name>
<thead>
  <tr>
  <th align="center">CBOR</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">Comment</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>integer</tt></td>
    <td align="center"><em>{sign}&#x2009;{&#x2008;</em><tt>0b</tt>|<tt>0o</tt>|<tt>0x</tt><em>}&#x2009;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>float</tt></td>
    <td align="center"><em>{sign}&#x2009;n</em><tt>.</tt><em>n&#x2009;{&#x2008;</em><tt>e&pm;</tt><em>n&#x2009;}</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>float</tt></td>
    <td align="center"><tt>NaN</tt></td>
    <td>
      Not a number.
    </td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>float</tt></td>
    <td align="center"><em>{sign}&#x2009;</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-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-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
    that 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>&#x200a;|&#x200a;<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.
      Key and value pairs are expressed as CBOR objects, separated by a <tt>':'</tt> character.
    </td>
    <td align="center"></td>
  </tr>
  <tr>
    <td align="center"><tt>#6.nnn</tt></td>
    <td align="center"><em>n</em>&#x2009;<tt>(</tt>&nbsp;<em>object</em>&nbsp;<tt>)</tt></td>
    <td>Tag holding a CBOR object.</td>
    <td align="center">1</td>
  </tr>
  <tr>
    <td align="center"><tt>#7.nnn</tt></td>
    <td align="center"><tt>simple(</tt><em>n</em><tt>)</tt></td>
    <td>Simple value.</td>
    <td align="center">1</td>
  </tr>
  <tr>
    <td align="center"></td>
    <td align="center"><tt>,</tt></td>
    <td>Separator character for CBOR sequences.</td>
    <td align="center">6</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>
      MUST (internally) be 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>
  <t>The <xref target="PLAYGROUND"/> is an excellent way of getting acquainted
  with CBOR and diagnostic notation.</t>

      </section>
      <section anchor="sequences">
      <name>CBOR Sequences</name>
      <t>
Decoders compliant with this specification MUST support CBOR sequences <xref target="RFC8742"/>.
    </t>
    <t>For decoders of "true" (binary) CBOR, there are additional requirements:</t>
    <ul>
    <li>It MUST be possible to decode one CBOR object at a time.</li>
    <li>The decoder MUST NOT do any assumptions about the nature of unread code (it might not even be CBOR).</li>
    </ul>
      </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>
CBOR/c does not introduce security issues beyond
what is already applicable to  <xref target="RFC8949"/>.
</t>
<t>
Poorly written tools and applications may certainly introduce security issues,
but this is 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"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8742.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="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="core.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 align="left">
<name>Integers</name>
<thead>
  <tr><th align="center">Diagnostic&nbsp;Notation</th>
  <th align="center">CBOR Encoding</th>
  <th align="center">Comment</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="core.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 is supposed to generate the shortest and most
correct representation of <xref target="IEEE754"/> numbers.</t>

<table align="left">
<name>Floating Point Numbers</name>
<thead>
  <tr><th align="center">Diagnostic&nbsp;Notation</th>
  <th align="center">CBOR Encoding</th>
  <th align="center">Comment</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>Negative infinity</td></tr>
<tr><td align="right"><tt>NaN</tt></td>
<td align="right"><tt>f97e00</tt></td>
<td>Not a number</td></tr>
<tr><td align="right"><tt>5.960464477539063e-8</tt></td>
<td align="right"><tt>f90001</tt></td>
<td>Smallest positive subnormal <tt>float16</tt></td></tr>
<tr><td align="right"><tt>0.00006097555160522461</tt></td>
<td align="right"><tt>f903ff</tt></td>
<td>Largest positive subnormal <tt>float16</tt></td></tr>
<tr><td align="right"><tt>0.00006103515625</tt></td>
<td align="right"><tt>f90400</tt></td>
<td>Smallest positive <tt>float16</tt></td></tr>
<tr><td align="right"><tt>65504.0</tt></td>
<td align="right"><tt>f97bff</tt></td>
<td>Largest positive <tt>float16</tt></td></tr>
<tr><td align="right"><tt>1.401298464324817e-45</tt></td>
<td align="right"><tt>fa00000001</tt></td>
<td>Smallest positive subnormal <tt>float32</tt></td></tr>
<tr><td align="right"><tt>1.1754942106924411e-38</tt></td>
<td align="right"><tt>fa007fffff</tt></td>
<td>Largest positive subnormal <tt>float32</tt></td></tr>
<tr><td align="right"><tt>1.1754943508222875e-38</tt></td>
<td align="right"><tt>fa00800000</tt></td>
<td>Smallest positive <tt>float32</tt></td></tr>
<tr><td align="right"><tt>3.4028234663852886e+38</tt></td>
<td align="right"><tt>fa7f7fffff</tt></td>
<td>Largest positive <tt>float32</tt></td></tr>
<tr><td align="right"><tt>5.0e-324</tt></td>
<td align="right"><tt>fb0000000000000001</tt></td>
<td>Smallest positive subnormal <tt>float64</tt></td></tr>
<tr><td align="right"><tt>2.225073858507201e-308</tt></td>
<td align="right"><tt>fb000fffffffffffff</tt></td>
<td>Largest positive subnormal <tt>float64</tt></td></tr>
<tr><td align="right"><tt>2.2250738585072014e-308</tt></td>
<td align="right"><tt>fb0010000000000000</tt></td>
<td>Smallest positive <tt>float64</tt></td></tr>
<tr><td align="right"><tt>1.7976931348623157e+308</tt></td>
<td align="right"><tt>fb7fefffffffffffff</tt></td>
<td>Largest positive <tt>float64</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 subnormal <tt>float16</tt></td></tr>
<tr><td align="right"><tt>-5.960464477539062e-8</tt></td>
<td align="right"><tt>fbbe6fffffffffffff</tt></td>
<td>Adjacent smallest negative subnormal <tt>float16</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 subnormal <tt>float16</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 <tt>float16</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 <tt>float16</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 subnormal <tt>float32</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 subnormal <tt>float32</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 <tt>float32</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 <tt>float32</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="core.misc">
        <name>Miscellaneous Items</name>
<t>This <em>normative</em> section holds a selection
of miscellaneous CBOR objects and their encoding.</t>
<table align="left">
<name>Miscellaneous Items</name>
<thead>
<tr>
<th align="center">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Diagnostic&nbsp;Notation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th align="center">CBOR Encoding</th>
<th align="center">Comment</th>
</tr>
</thead>
<tbody>
<tr><td><tt>true</tt></td>
<td><tt>f5</tt></td>
<td>Boolean true</td></tr>
<tr><td><tt>null</tt></td>
<td><tt>f6</tt></td>
<td>Null</td></tr>
<tr><td><tt>simple(59)</tt></td>
<td><tt>f83b</tt></td>
<td>Simple value</td></tr>
<tr><td><tt>0("2025-03-30T12:24:16Z")</tt></td>
<td><tt>c074323032352d30332d33<br/>
305431323a32343a31365a</tt></td>
<td>ISO date/time</td></tr>
<tr><td><tt>[1, [2, 3], [4, 5]]</tt></td>
<td><tt>8301820203820405</tt></td>
<td>Array combinations</td></tr>
<tr><td><tt>{<br/>
&nbsp;&nbsp;"a": 0,<br/>
&nbsp;&nbsp;"b": 1,<br/>
&nbsp;&nbsp;"aa": 2<br/>
}</tt></td>
<td><tt>a361610161620262616103</tt></td>
<td>Map object</td></tr>
<tr><td><tt>h'48656c6c6f2043424f5221'</tt></td>
<td><tt>4b48656c6c6f2043424f5221</tt></td>
<td>Binary string</td></tr>
<tr><td><tt>"&#x1f680; science"</tt></td>
<td><tt>6cf09f9a8020736369656e6365</tt></td>
<td>Text string with emoji</td></tr>
</tbody>
</table>

    </section>
    <section anchor="core.invalid">
      <name>Invalid Encodings</name>
      <t>The following table holds a selection of CBOR-encoded objects, not permitted by CBOR/c.</t>
<table align="left">
<name>Invalid Encodings</name>
<thead>
  <tr><th align="center">CBOR Encoding</th><th align="center">Diagnostic Notation</th>
  <th align="center">Comment</th><th align="center">Notes</th></tr>
</thead>
<tbody>
<tr>
<td><tt>a2616201616100</tt></td>
<td><tt>{<br/>
&nbsp;&nbsp;"b": 1,<br/>
&nbsp;&nbsp;"a": 0<br/>
}</tt></td>
<td>Improper map key ordering</td>
<td align="center">1, 2</td>
</tr>

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

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

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

<tr>
<td><tt>fa7fc00000</tt></td>
<td><tt>NaN</tt></td>
<td>Not in shortest encoding</td>
<td align="center">1, 2</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, 2</td>
</tr>

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

<tr>
<td><tt>5f4101420203ff</tt></td>
<td><tt>(_ h'01', h'0203')</tt></td>
<td>Indefinite length object</td>
<td align="center">2</td>
</tr>
<tr>
<td><tt>fc</tt></td>
<td></td>
<td>Reserved</td>
<td></td>
</tr>
<tr>
<td><tt>f818</tt></td>
<td></td>
<td>Invalid simple value</td>
<td></td>
</tr>
<tr>
<td><tt>5b0010000000000000</tt></td>
<td></td>
<td>Extremely large <tt>bstr</tt> length indicator: 4503599627370496</td>
<td></td>
</tr>

</tbody>
</table>
<ol>
<li>See also <xref target="legacy.systems"/>.</li>
<li><em>Non-deterministically</em> encoded CBOR supported by <xref target="RFC8949"/>.</li>
</ol>

    </section>

    </section>
    
    <section anchor="embedded.signatures">
      <name>Embedded Signatures</name>
      <t>This is a <em>non-normative</em> appendix showing how CBOR/c
      can be used for supporting embedded signatures.</t>
      <t>The primary advantages with <em>embedded</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>Embedded 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 CBOR/c 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 CBOR/c, 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
        embedded 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 embedded 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 CBOR/c, 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="core.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 CBOR/c, also is compliant with <xref target="RFC8949"/>
(as well as with <xref target="CBOR.ME"/>),
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 (CBOR/c 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 CBOR/c 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
CBOR/c implementation MUST maintain deterministic encoding.
See also <xref target="core.invalid"/>.</t>
    </section>

    <section anchor="tools.online">
      <name>Compatible Online Tools</name>
      <t>For testing and learning about CBOR/c,
      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 CBOR/c 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 sub-section added.</t>
        <t>Diagnostic Notation 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>
        <li>
        <t>05:</t>
        <t>Regression bug fix</t>
        </li>
        <li>
        <t>06:</t>
        <t>Media type added</t>
        </li>
        <li>
        <t>07-&gt;00:</t>
        <t>Renamed from "Universal CBOR" to "CBOR Base"</t>
        <t>Design Goals added</t>
        <t>CBOR Sequences added</t>
        </li>
        <li>
        <t>01:</t>
        <t>#7.nnn (simple) added</t>
        <t>Language nits</t>
        </li>
        <li>
        <t>02-&gt;00:</t>
        <t>Renamed from "CBOR Base" to "CBOR Core"</t>
        <t>Language nits</t>
        <t>Miscellaneous Items added</t>
        </li>
        <li>
        <t>01:</t>
        <t>Language nits</t>
        <t>&lt;table align="left"&gt;</t>
        </li>
        <li>
        <t>02:</t>
        <t>Editorial</t>
        </li>
        <li>
        <t>03:</t>
        <t>Added Date decode/reencode example</t>
        </li>
        <li>
        <t>04:</t>
        <t>Editorial</t>
        <t>Added bstr and tstr to Protocol Primitives</t>
        </li>
        <li>
        <t>05:</t>
        <t>Enveloped =&gt; Embedded (signature)</t>
        </li>
        <li>
        <t>06:</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>
<t>
Non-exhaustive list of people who directly (and sometimes indirectly) contributed
to this specification include: Carsten Bormann,
Alan DeKok, Vadim Goncharov, Joe Hildebrand,
Laurence Lundblade, Rohan Mahy,
Michael Richardson, Göran Selander, and Orie Steele.
</t>
    </section>
    
 </back>
</rfc>
