<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>

<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="info"
     docName="draft-ayerbe-trip-protocol-00"
     ipr="trust200902"
     submissionType="independent"
     version="3">

  <front>
    <title abbrev="TRIP">
      TRIP: Trajectory-based Recognition of Identity Proof
    </title>

    <seriesInfo name="Internet-Draft" value="draft-ayerbe-trip-protocol-00"/>

    <author fullname="Camilo Ayerbe" initials="C." surname="Ayerbe">
      <organization>ULISSY s.r.l.</organization>
      <address>
        <postal>
          <street>Via Gaetano Sacchi 16</street>
          <city>Roma</city>
          <region>RM</region>
          <code>00153</code>
          <country>IT</country>
        </postal>
        <email>cayerbe@gmail.com</email>
      </address>
    </author>

    <date year="2026" month="February" day="01"/>

    <area>Security</area>
    <workgroup>Independent Submission</workgroup>

    <keyword>identity</keyword>
    <keyword>trajectory</keyword>
    <keyword>proof-of-trajectory</keyword>
    <keyword>geospatial</keyword>
    <keyword>cryptography</keyword>

    <abstract>
      <t>
        This document specifies the Trajectory-based Recognition of
        Identity Proof (TRIP) protocol, a decentralized mechanism for
        establishing claims of physical-world presence through
        cryptographically signed, spatially quantized location
        attestations called "breadcrumbs."  Breadcrumbs are chained
        into an append-only log, bundled into verifiable epochs, and
        distilled into a Trajectory Identity Token (TIT) that serves
        as a persistent pseudonymous identifier.  Trust in a TIT
        accumulates through spatiotemporal diversity of the underlying
        trajectory rather than through biometric capture or centralized
        credential issuance.  TRIP is designed to be transport-agnostic
        and operates independently of any particular naming system,
        blockchain, or application layer.
      </t>
    </abstract>
  </front>

  <middle>

    <!-- ============================================================ -->
    <section anchor="introduction" numbered="true" toc="include">
      <name>Introduction</name>
      <t>
        Conventional approaches to proving that an online actor
        corresponds to a physical human being rely on biometric
        capture, government-issued documents, or knowledge-based
        challenges.  Each technique introduces a centralized trust
        anchor, creates honeypots of personally identifiable
        information (PII), and is susceptible to replay or deepfake
        attacks.
      </t>
      <t>
        TRIP takes a fundamentally different approach: it treats
        sustained physical movement through the real world as evidence
        of embodied existence.  A TRIP-enabled device periodically
        records its position as a "breadcrumb"--a compact, privacy-
        preserving, cryptographically signed attestation that the
        holder of a specific Ed25519 key pair was present in a
        particular spatial cell at a particular time.  An adversary
        who controls only digital infrastructure cannot fabricate a
        plausible trajectory because doing so requires controlling
        radio-frequency environments (GPS, Wi-Fi, cellular, IMU) at
        many geographic locations over extended periods.
      </t>
      <t>
        This document specifies the data structures, algorithms, and
        verification procedures that constitute the TRIP protocol.
        It intentionally omits transport bindings, naming-system
        integration, and blockchain anchoring, all of which are
        expected to be addressed in companion specifications.
      </t>

      <section anchor="requirements-language" numbered="true" toc="include">
        <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 anchor="terminology" numbered="true" toc="include">
        <name>Terminology</name>
        <dl>
          <dt>Breadcrumb</dt>
          <dd>
            A single, signed attestation of spatiotemporal presence.
            The atomic unit of the TRIP protocol.
          </dd>
          <dt>Trajectory</dt>
          <dd>
            An ordered, append-only chain of breadcrumbs produced by
            a single identity key pair.
          </dd>
          <dt>Epoch</dt>
          <dd>
            A batch of consecutive breadcrumbs whose aggregate
            integrity is attested by a Merkle root and a signature.
          </dd>
          <dt>Trajectory Identity Token (TIT)</dt>
          <dd>
            A 16-byte identifier derived from the public key and
            genesis breadcrumb, used as a persistent pseudonym.
          </dd>
          <dt>H3 Cell</dt>
          <dd>
            A hexagonal cell identifier from the H3 geospatial
            indexing system, used as the privacy-preserving spatial
            coordinate in breadcrumbs.
          </dd>
          <dt>Context Digest</dt>
          <dd>
            A SHA-256 hash of ambient environmental signals (Wi-Fi
            BSSIDs, cell tower IDs, IMU readings) that provides
            corroborating evidence for a breadcrumb's claimed
            location without revealing the raw signals.
          </dd>
          <dt>Trust Score</dt>
          <dd>
            A numerical value reflecting the spatiotemporal diversity
            and longevity of a trajectory, computed according to a
            defined trust function.
          </dd>
        </dl>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="architecture" numbered="true" toc="include">
      <name>Protocol Architecture</name>
      <t>
        TRIP defines three layers of abstraction:
      </t>
      <ol type="1">
        <li>
          <strong>Breadcrumb Layer</strong> -- Production and
          validation of individual signed attestations.
        </li>
        <li>
          <strong>Epoch Layer</strong> -- Aggregation of breadcrumbs
          into verifiable batches with Merkle integrity.
        </li>
        <li>
          <strong>Trust Layer</strong> -- Computation of a reputation
          score from the spatiotemporal properties of a trajectory.
        </li>
      </ol>
      <t>
        All cryptographic operations use Ed25519 <xref target="RFC8032"/>
        for signing and SHA-256 <xref target="RFC6234"/> for hashing.
        Spatial coordinates are quantized to the H3 hexagonal grid
        system before any storage or transmission.
      </t>

      <section anchor="identity-model" numbered="true" toc="include">
        <name>Identity Model</name>
        <t>
          A TRIP identity is an Ed25519 key pair.  The 32-byte public
          key is the identity.  There is no registration authority;
          any entity capable of generating a valid Ed25519 key pair
          MAY participate in the protocol.  The private key MUST be
          stored in a secure enclave or hardware-backed keystore and
          MUST NOT leave the originating device.
        </t>
        <t>
          A single physical entity MAY maintain multiple TRIP
          identities.  The protocol makes no attempt to link multiple
          identities to a single entity; such linkage is explicitly a
          non-goal.
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="breadcrumb" numbered="true" toc="include">
      <name>Breadcrumb Specification</name>

      <section anchor="breadcrumb-structure" numbered="true" toc="include">
        <name>Data Structure</name>
        <t>
          A breadcrumb is a fixed-schema record consisting of the
          following fields, serialized as a CBOR <xref target="RFC8949"/>
          map with integer keys:
        </t>

        <table anchor="breadcrumb-fields" align="center">
          <name>Breadcrumb Fields</name>
          <thead>
            <tr>
              <th>Key</th>
              <th>CBOR Label</th>
              <th>Type</th>
              <th>Bytes</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>index</td>
              <td>1</td>
              <td>uint</td>
              <td>1-9</td>
              <td>Zero-based sequence number within the trajectory</td>
            </tr>
            <tr>
              <td>identity</td>
              <td>2</td>
              <td>bstr</td>
              <td>32</td>
              <td>Ed25519 public key of the producer</td>
            </tr>
            <tr>
              <td>timestamp</td>
              <td>3</td>
              <td>tag(1)</td>
              <td>5-9</td>
              <td>CBOR epoch-based date/time (seconds since Unix epoch)</td>
            </tr>
            <tr>
              <td>cell</td>
              <td>4</td>
              <td>uint</td>
              <td>9</td>
              <td>H3 cell index (64-bit unsigned integer)</td>
            </tr>
            <tr>
              <td>resolution</td>
              <td>5</td>
              <td>uint</td>
              <td>1</td>
              <td>H3 resolution level (0-15)</td>
            </tr>
            <tr>
              <td>context</td>
              <td>6</td>
              <td>bstr</td>
              <td>32</td>
              <td>SHA-256 context digest</td>
            </tr>
            <tr>
              <td>previous</td>
              <td>7</td>
              <td>bstr / null</td>
              <td>32 / 1</td>
              <td>SHA-256 hash of preceding breadcrumb, or null for genesis</td>
            </tr>
            <tr>
              <td>meta</td>
              <td>8</td>
              <td>map</td>
              <td>variable</td>
              <td>OPTIONAL metadata flags (battery, accuracy, etc.)</td>
            </tr>
            <tr>
              <td>signature</td>
              <td>9</td>
              <td>bstr</td>
              <td>64</td>
              <td>Ed25519 signature over fields 1-8</td>
            </tr>
          </tbody>
        </table>

        <t>
          The canonical CBOR encoding of fields 1 through 8
          (inclusive), sorted by CBOR label in ascending integer order,
          constitutes the "signable payload."  The signature in field 9
          is an Ed25519 signature over this signable payload.
        </t>
      </section>

      <section anchor="breadcrumb-hash" numbered="true" toc="include">
        <name>Breadcrumb Hash</name>
        <t>
          The breadcrumb hash is the SHA-256 digest of the complete
          canonical CBOR encoding of the breadcrumb (fields 1 through
          9 inclusive).  This hash serves as the chain link: the
          "previous" field (label 7) of breadcrumb N+1 MUST contain
          the breadcrumb hash of breadcrumb N.
        </t>
        <figure anchor="fig-hash">
          <name>Breadcrumb Hash Computation</name>
          <artwork type="ascii-art"><![CDATA[
   BreadcrumbHash(B) = SHA-256(CBOR-Canonical(B[1..9]))
   B[N+1].previous   = BreadcrumbHash(B[N])
   B[0].previous     = null
          ]]></artwork>
        </figure>
      </section>

      <section anchor="spatial-quantization" numbered="true" toc="include">
        <name>Spatial Quantization</name>
        <t>
          Raw geographic coordinates (latitude, longitude) MUST NOT
          appear in any breadcrumb or in any message transmitted by a
          TRIP implementation.  All spatial data MUST be quantized to
          an H3 cell index before storage or transmission.
        </t>
        <t>
          The H3 geospatial indexing system <xref target="H3"/> partitions the Earth's
          surface into a hierarchy of hexagonal cells at 16 resolution
          levels (0-15).  The resolution determines the trade-off
          between location privacy and spatial precision:
        </t>

        <table anchor="h3-resolutions" align="center">
          <name>H3 Resolution Properties (Selected)</name>
          <thead>
            <tr>
              <th>Resolution</th>
              <th>Avg. Area (km2)</th>
              <th>Avg. Edge (km)</th>
              <th>TRIP Usage</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>7</td>
              <td>5.161</td>
              <td>1.22</td>
              <td>Public disclosure / city-level</td>
            </tr>
            <tr>
              <td>10</td>
              <td>0.015</td>
              <td>0.066</td>
              <td>Default breadcrumb resolution</td>
            </tr>
            <tr>
              <td>12</td>
              <td>0.0003</td>
              <td>0.010</td>
              <td>Precise / commercial</td>
            </tr>
          </tbody>
        </table>

        <t>
          Implementations SHOULD default to resolution 10.
          Implementations MUST support resolutions 7 through 12
          inclusive.  A verifier MAY accept breadcrumbs at resolutions
          outside this range but SHOULD apply reduced trust weight.
        </t>
      </section>

      <section anchor="context-digest" numbered="true" toc="include">
        <name>Context Digest Construction</name>
        <t>
          The context digest provides corroborating environmental
          evidence for a claimed location without disclosing the raw
          sensor data.  It is constructed as follows:
        </t>
        <ol type="1">
          <li>
            Collect available ambient signals: Wi-Fi BSSIDs, cellular
            tower identifiers, and inertial measurement unit (IMU)
            readings.
          </li>
          <li>
            <t>
              Construct a pipe-delimited string of tagged components
              in the following order:
            </t>
            <ul>
              <li>"h3:" followed by the H3 cell hex string</li>
              <li>"ts:" followed by the timestamp bucketed to 5-minute intervals (Unix minutes / 5 * 5)</li>
              <li>"wifi:" followed by the first 16 hex characters of SHA-256(sorted comma-joined BSSIDs), if available</li>
              <li>"cell:" followed by the first 16 hex characters of SHA-256(sorted comma-joined tower IDs), if available</li>
              <li>"imu:" followed by the first 16 hex characters of SHA-256(IMU vector string), if available</li>
            </ul>
          </li>
          <li>
            Compute SHA-256 of the resulting pipe-delimited string.
          </li>
        </ol>
        <figure anchor="fig-context">
          <name>Context Digest Example</name>
          <artwork type="ascii-art"><![CDATA[
   input  = "h3:8a2a1072b59ffff|ts:29145660|wifi:a3b2c1d4e5f67890"
   digest = SHA-256(input)
          ]]></artwork>
        </figure>
        <t>
          If no ambient signals are available, the context digest
          MUST still be computed from the h3 and ts components alone.
          A verifier SHOULD assign higher trust weight to breadcrumbs
          with richer context digests.
        </t>
      </section>

      <section anchor="genesis" numbered="true" toc="include">
        <name>Genesis Breadcrumb</name>
        <t>
          The first breadcrumb in a trajectory (index 0) is the
          genesis breadcrumb.  Its "previous" field MUST be null
          (CBOR simple value 22).  The genesis breadcrumb establishes
          the binding between an Ed25519 public key and its
          trajectory chain.
        </t>
      </section>

      <section anchor="velocity-check" numbered="true" toc="include">
        <name>Velocity Plausibility</name>
        <t>
          Before accepting a breadcrumb, a verifier SHOULD check that
          the implied velocity between consecutive breadcrumbs does
          not exceed a configurable maximum.  The implied velocity is
          computed using the Haversine distance <xref target="HAVERSINE"/> between the H3 cell
          centers divided by the time difference.
        </t>
        <t>
          The following entity speed classes are RECOMMENDED:
        </t>

        <table anchor="speed-classes" align="center">
          <name>Entity Speed Classes</name>
          <thead>
            <tr>
              <th>Class</th>
              <th>Max Speed (km/h)</th>
              <th>Typical Entity</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>human</td>
              <td>200</td>
              <td>Pedestrian, cyclist, public transit</td>
            </tr>
            <tr>
              <td>vehicle</td>
              <td>500</td>
              <td>Automobile, train</td>
            </tr>
            <tr>
              <td>drone</td>
              <td>300</td>
              <td>Unmanned aerial vehicle</td>
            </tr>
            <tr>
              <td>anchor</td>
              <td>0</td>
              <td>Fixed IoT device, kiosk</td>
            </tr>
          </tbody>
        </table>

        <t>
          An entity class tag MAY be included in the meta field
          (CBOR label 8) under key "entity_class".  Verifiers
          SHOULD reject breadcrumbs that exceed the maximum speed
          for the declared entity class.  If no entity class is
          declared, verifiers SHOULD apply the "human" speed limit.
        </t>
      </section>

      <section anchor="dedup" numbered="true" toc="include">
        <name>Location Deduplication</name>
        <t>
          A conforming producer MUST NOT emit a breadcrumb whose H3
          cell is identical to the H3 cell of the immediately
          preceding breadcrumb in the same trajectory.  This
          constraint enforces the core principle that trajectory
          identity requires physical movement.  Implementations
          SHOULD additionally enforce a minimum geographic distance
          (RECOMMENDED: 50 meters) between consecutive breadcrumbs.
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="tit" numbered="true" toc="include">
      <name>Trajectory Identity Token (TIT)</name>
      <t>
        The Trajectory Identity Token is a compact, deterministic
        identifier derived from the identity key and the genesis
        breadcrumb.  It serves as a persistent pseudonym that is
        shorter than a full public key yet remains cryptographically
        bound to both the key and its origin point.
      </t>
      <figure anchor="fig-tit">
        <name>TIT Derivation</name>
        <artwork type="ascii-art"><![CDATA[
   tit_input  = identity_public_key || BreadcrumbHash(genesis)
   tit_full   = SHA-256(tit_input)
   TIT        = tit_full[0..15]     // first 16 bytes (128 bits)
        ]]></artwork>
      </figure>
      <t>
        The TIT is 16 bytes (128 bits).  Implementations SHOULD
        represent TITs as 32-character lowercase hexadecimal strings
        for display and interchange.
      </t>
      <t>
        A TIT is immutable once computed.  If an entity wishes to
        start a new trajectory (e.g., after key compromise), it MUST
        generate a new key pair, which will produce a new TIT.  No
        mechanism exists within TRIP to link old and new TITs; such
        linkage is a higher-layer concern.
      </t>
    </section>

    <!-- ============================================================ -->
    <section anchor="epochs" numbered="true" toc="include">
      <name>Epoch Specification</name>

      <section anchor="epoch-structure" numbered="true" toc="include">
        <name>Data Structure</name>
        <t>
          An epoch aggregates a contiguous range of breadcrumbs into
          a single verifiable unit.  Epochs enable efficient
          verification: a verifier can check the epoch Merkle root
          and signature without examining every individual breadcrumb.
        </t>

        <table anchor="epoch-fields" align="center">
          <name>Epoch Fields</name>
          <thead>
            <tr>
              <th>Key</th>
              <th>CBOR Label</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>epoch_index</td>
              <td>1</td>
              <td>uint</td>
              <td>Zero-based epoch sequence number</td>
            </tr>
            <tr>
              <td>identity</td>
              <td>2</td>
              <td>bstr</td>
              <td>Ed25519 public key (32 bytes)</td>
            </tr>
            <tr>
              <td>start_time</td>
              <td>3</td>
              <td>tag(1)</td>
              <td>Timestamp of first breadcrumb in epoch</td>
            </tr>
            <tr>
              <td>end_time</td>
              <td>4</td>
              <td>tag(1)</td>
              <td>Timestamp of last breadcrumb in epoch</td>
            </tr>
            <tr>
              <td>start_index</td>
              <td>5</td>
              <td>uint</td>
              <td>Breadcrumb index of first entry</td>
            </tr>
            <tr>
              <td>end_index</td>
              <td>6</td>
              <td>uint</td>
              <td>Breadcrumb index of last entry</td>
            </tr>
            <tr>
              <td>merkle_root</td>
              <td>7</td>
              <td>bstr</td>
              <td>SHA-256 Merkle root of breadcrumb hashes (32 bytes)</td>
            </tr>
            <tr>
              <td>count</td>
              <td>8</td>
              <td>uint</td>
              <td>Number of breadcrumbs in epoch</td>
            </tr>
            <tr>
              <td>previous_epoch</td>
              <td>9</td>
              <td>bstr / null</td>
              <td>Hash of preceding epoch, or null for first epoch</td>
            </tr>
            <tr>
              <td>signature</td>
              <td>10</td>
              <td>bstr</td>
              <td>Ed25519 signature over fields 1-9 (64 bytes)</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section anchor="merkle-tree" numbered="true" toc="include">
        <name>Merkle Tree Construction</name>
        <t>
          The Merkle tree is a binary tree constructed from the
          breadcrumb hashes within the epoch.  Leaves are the
          SHA-256 hashes of individual breadcrumbs.  Internal nodes
          are computed as SHA-256(left_child || right_child).  If the
          number of leaves is odd, the last leaf is duplicated.
        </t>
        <figure anchor="fig-merkle">
          <name>Merkle Tree for an Epoch of 4 Breadcrumbs</name>
          <artwork type="ascii-art"><![CDATA[
                     MerkleRoot
                    /          \
               H(AB)            H(CD)
              /     \          /     \
          H(B0)   H(B1)   H(B2)   H(B3)
          ]]></artwork>
        </figure>
        <t>
          where H(Bn) = BreadcrumbHash(breadcrumb_n) and
          H(AB) = SHA-256(H(B0) || H(B1)).
        </t>
      </section>

      <section anchor="epoch-bundling" numbered="true" toc="include">
        <name>Bundling Rules</name>
        <t>
          A producer SHOULD bundle an epoch when the number of
          unbundled breadcrumbs reaches or exceeds 100.
          Implementations MAY use a different threshold but
          MUST NOT create epochs with fewer than 10 breadcrumbs
          (except for the final epoch if the trajectory is being
          closed).
        </t>
        <t>
          Epochs MUST be sequential and contiguous: epoch N+1 MUST
          begin at the breadcrumb immediately following the last
          breadcrumb of epoch N.  No breadcrumb may belong to more
          than one epoch, and no breadcrumb may be omitted from
          an epoch.
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="trust" numbered="true" toc="include">
      <name>Trust Computation</name>

      <section anchor="trust-model" numbered="true" toc="include">
        <name>Trust Model Overview</name>
        <t>
          TRIP trust reflects the difficulty of fabricating a
          trajectory.  A trajectory that visits many distinct spatial
          cells over a long duration is harder to fake than one
          confined to a small area or short time span.  The trust
          model quantifies this intuition through three components:
          trajectory density, spatial diversity, and temporal decay.
        </t>
      </section>

      <section anchor="trust-score" numbered="true" toc="include">
        <name>Trust Score Function</name>
        <t>
          The trust score T for a trajectory is computed using a
        Parisi percolation model <xref target="PARISI"/>:
        </t>
        <figure anchor="fig-trust">
          <name>Trust Score Computation</name>
          <artwork type="ascii-art"><![CDATA[
   T = D(t) * S * k_percolation

   where:

   D(t) = exp(-(t - t_last)^2 / (2 * tau^2))
          Gaussian temporal decay function
          t       = current time
          t_last  = timestamp of most recent breadcrumb
          tau     = decay half-life (RECOMMENDED: 30 days)

   S     = unique_cells / total_breadcrumbs
           Spatial diversity ratio (0.0 to 1.0)
           unique_cells = count of distinct H3 cells visited

   k_percolation = min(breadcrumb_count / 100.0, k_max)
                   Parisi percolation factor [PARISI]
                   k_max = 7 (RECOMMENDED)
          ]]></artwork>
        </figure>
        <t>
          A verifier MAY apply additional weighting factors (e.g.,
          context digest richness, geographic spread) but MUST
          compute at least the base trust score defined above for
          interoperability.
        </t>
      </section>

      <section anchor="trust-thresholds" numbered="true" toc="include">
        <name>Trust Thresholds</name>
        <t>
          TRIP does not mandate specific trust thresholds for
          application-level decisions.  However, the following
          reference thresholds are RECOMMENDED for interoperability:
        </t>

        <table anchor="trust-levels" align="center">
          <name>Reference Trust Thresholds</name>
          <thead>
            <tr>
              <th>Level</th>
              <th>Min. Score</th>
              <th>Min. Breadcrumbs</th>
              <th>Typical Use</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>anonymous</td>
              <td>0</td>
              <td>0</td>
              <td>Key pair exists, no trajectory</td>
            </tr>
            <tr>
              <td>emerging</td>
              <td>0.5</td>
              <td>50</td>
              <td>Read-only access, limited API</td>
            </tr>
            <tr>
              <td>established</td>
              <td>1.0</td>
              <td>100</td>
              <td>Handle claiming, messaging</td>
            </tr>
            <tr>
              <td>trusted</td>
              <td>3.0</td>
              <td>300</td>
              <td>Financial operations, publishing</td>
            </tr>
            <tr>
              <td>sovereign</td>
              <td>5.0</td>
              <td>500+</td>
              <td>Full protocol participation</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="verification" numbered="true" toc="include">
      <name>Verification Procedures</name>

      <section anchor="verify-breadcrumb" numbered="true" toc="include">
        <name>Breadcrumb Verification</name>
        <t>
          A verifier MUST perform the following checks on each
          breadcrumb, in order:
        </t>
        <ol type="1">
          <li>
            Decode the CBOR payload and verify that all mandatory
            fields (labels 1-7, 9) are present.
          </li>
          <li>
            Verify that the identity field (label 2) is a valid
            32-byte Ed25519 public key.
          </li>
          <li>
            Reconstruct the signable payload from fields 1-8 in
            canonical CBOR encoding.
          </li>
          <li>
            Verify the Ed25519 signature (label 9) against the
            signable payload using the identity public key.
          </li>
          <li>
            If index > 0, verify that the "previous" field (label 7)
            matches the hash of the preceding breadcrumb.
          </li>
          <li>
            If index == 0, verify that the "previous" field is null.
          </li>
          <li>
            Verify that the timestamp is not in the future (with a
            tolerance of RECOMMENDED 5 minutes for clock skew).
          </li>
          <li>
            OPTIONAL: Verify velocity plausibility relative to the
            preceding breadcrumb (<xref target="velocity-check"/>).
          </li>
        </ol>
      </section>

      <section anchor="verify-epoch" numbered="true" toc="include">
        <name>Epoch Verification</name>
        <t>
          A verifier MUST perform the following checks on each epoch:
        </t>
        <ol type="1">
          <li>
            Verify the Ed25519 signature over fields 1-9.
          </li>
          <li>
            Reconstruct the Merkle tree from the constituent
            breadcrumb hashes and verify it matches the declared
            merkle_root.
          </li>
          <li>
            Verify that start_index and end_index define a
            contiguous range.
          </li>
          <li>
            Verify that count == end_index - start_index + 1.
          </li>
          <li>
            If epoch_index > 0, verify that previous_epoch matches
            the hash of the preceding epoch.
          </li>
        </ol>
      </section>

      <section anchor="verify-tit" numbered="true" toc="include">
        <name>TIT Verification</name>
        <t>
          To verify a claimed TIT, a verifier MUST:
        </t>
        <ol type="1">
          <li>
            Obtain the claimant's Ed25519 public key and genesis
            breadcrumb.
          </li>
          <li>
            Verify the genesis breadcrumb per
            <xref target="verify-breadcrumb"/>.
          </li>
          <li>
            Compute the TIT per <xref target="tit"/> and compare
            with the claimed value.
          </li>
        </ol>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="cbor-encoding" numbered="true" toc="include">
      <name>CBOR Encoding</name>
      <t>
        TRIP messages MUST be encoded using CBOR
        <xref target="RFC8949"/>.  The canonical encoding follows
        the deterministic CBOR rules specified in Section 4.2 of
        <xref target="RFC8949"/>:
      </t>
      <ul>
        <li>
          Map keys MUST be sorted in ascending integer order.
        </li>
        <li>
          Integers MUST use the shortest encoding.
        </li>
        <li>
          Byte strings and text strings MUST use definite-length
          encoding.
        </li>
      </ul>
      <t>
        Implementations that also support JSON interchange (e.g., for
        debugging or logging) SHOULD use the following canonical JSON
        rules: keys sorted alphabetically, numbers normalized
        (integers where possible), and no trailing whitespace.
      </t>

      <section anchor="cddl" numbered="true" toc="include">
        <name>CDDL Schema</name>
        <t>
          The following CDDL <xref target="RFC8610"/> defines the
          TRIP data structures:
        </t>
        <sourcecode type="cddl"><![CDATA[
; TRIP Protocol CDDL Schema

breadcrumb = {
  1 => uint,                ; index
  2 => bstr .size 32,       ; identity (Ed25519 public key)
  3 => #6.1(number),        ; timestamp (epoch seconds)
  4 => uint,                ; cell (H3 index)
  5 => uint .le 15,         ; resolution (0-15)
  6 => bstr .size 32,       ; context digest (SHA-256)
  7 => bstr .size 32 / nil, ; previous hash or null
  ? 8 => meta-map,          ; optional metadata
  9 => bstr .size 64,       ; signature (Ed25519)
}

meta-map = {
  ? "battery"      => uint .le 100,
  ? "accuracy"     => float,
  ? "network"      => tstr,
  ? "entity_class" => entity-class,
  ? "manual"       => bool,
  * tstr => any,
}

entity-class = "human" / "vehicle" / "drone" / "anchor"

epoch = {
  1  => uint,                ; epoch_index
  2  => bstr .size 32,       ; identity
  3  => #6.1(number),        ; start_time
  4  => #6.1(number),        ; end_time
  5  => uint,                ; start_index
  6  => uint,                ; end_index
  7  => bstr .size 32,       ; merkle_root
  8  => uint,                ; count
  9  => bstr .size 32 / nil, ; previous_epoch hash or null
  10 => bstr .size 64,       ; signature
}

trajectory-identity-token = bstr .size 16
        ]]></sourcecode>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="security" numbered="true" toc="include">
      <name>Security Considerations</name>

      <section anchor="threat-model" numbered="true" toc="include">
        <name>Threat Model</name>
        <t>
          TRIP assumes the following threat model:
        </t>
        <ul>
          <li>
            <strong>Private key security:</strong> The Ed25519 private
            key is assumed to be held in a secure enclave.  If the
            private key is compromised, the attacker can produce
            valid breadcrumbs.  Key compromise is outside the scope
            of TRIP; key management and revocation are higher-layer
            concerns.
          </li>
          <li>
            <strong>GPS spoofing:</strong> An attacker with a
            software-defined radio can spoof GPS signals in a
            localized area.  The context digest (<xref target="context-digest"/>)
            mitigates this by incorporating Wi-Fi BSSID and cellular
            tower data that are independent of GPS.  Spoofing all
            signal sources simultaneously at diverse locations is
            significantly harder.
          </li>
          <li>
            <strong>Virtual environment:</strong> An attacker running
            the TRIP client in an emulator can feed arbitrary
            location data.  The velocity plausibility check
            (<xref target="velocity-check"/>) and the requirement for
            sustained diversity over time make this attack
            progressively more expensive.
          </li>
          <li>
            <strong>Colocation attack:</strong> Two colluding devices
            can generate breadcrumbs at the same locations, but each
            device produces an independent trajectory under its own
            key.  Cross-trajectory correlation is a verifier-side
            heuristic and is outside the scope of this specification.
          </li>
        </ul>
      </section>

      <section anchor="crypto-agility" numbered="true" toc="include">
        <name>Cryptographic Agility</name>
        <t>
          This specification mandates Ed25519 for signatures and
          SHA-256 for hashing.  Future versions of TRIP MAY introduce
          algorithm negotiation.  Implementations SHOULD be designed
          to allow algorithm substitution without protocol-level
          changes.
        </t>
      </section>

      <section anchor="replay" numbered="true" toc="include">
        <name>Replay Protection</name>
        <t>
          The monotonically increasing index and the chaining via
          the "previous" hash field provide replay protection within
          a single trajectory.  A replayed breadcrumb will fail the
          chain integrity check.  Cross-trajectory replay (using
          breadcrumbs from identity A in a trajectory of identity B)
          will fail signature verification.
        </t>
      </section>

      <section anchor="dos" numbered="true" toc="include">
        <name>Denial of Service</name>
        <t>
          An attacker can generate large numbers of breadcrumbs to
          consume verifier resources.  Verifiers SHOULD rate-limit
          breadcrumb submission per identity and MAY require a
          minimum trust score before accepting further breadcrumbs
          for resource-intensive operations.
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="privacy" numbered="true" toc="include">
      <name>Privacy Considerations</name>

      <section anchor="location-privacy" numbered="true" toc="include">
        <name>Location Privacy</name>
        <t>
          TRIP's primary privacy mechanism is H3 quantization.  By
          design, a breadcrumb reveals only that the producer was
          within a hexagonal cell of known area--not the precise
          GPS coordinates.  At the default resolution 10, each cell
          covers approximately 15,000 square meters (0.015 km2),
          providing meaningful location privacy in urban environments.
        </t>
        <t>
          Implementations MUST NOT store raw GPS coordinates after
          H3 quantization.  Implementations SHOULD provide users
          with the ability to choose their preferred resolution
          level, understanding that lower resolutions (larger cells)
          provide more privacy at the cost of reduced trust
          accumulation rate.
        </t>
      </section>

      <section anchor="trajectory-privacy" numbered="true" toc="include">
        <name>Trajectory Correlation</name>
        <t>
          A trajectory is intrinsically linkable: all breadcrumbs
          share the same identity key.  This is by design, as trust
          accumulation requires identity continuity.  However, a user
          who desires unlinkability across contexts MAY maintain
          separate TRIP identities (key pairs) for separate contexts.
        </t>
        <t>
          Verifiers SHOULD disclose their data retention policies.
          Breadcrumbs presented for verification need not be stored
          by the verifier after trust computation.
        </t>
      </section>

      <section anchor="context-privacy" numbered="true" toc="include">
        <name>Context Digest Privacy</name>
        <t>
          The context digest is a one-way hash.  Wi-Fi BSSIDs, cell
          tower IDs, and IMU readings cannot be recovered from the
          digest.  However, an attacker who knows the Wi-Fi
          environment at a specific location and time could
          reconstruct the digest and confirm the producer's presence.
          This is a known acceptable trade-off: the digest provides
          corroboration, not concealment.
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="iana" numbered="true" toc="include">
      <name>IANA Considerations</name>
      <t>
        This document has no IANA actions at this time.  A future
        revision may request:
      </t>
      <ul>
        <li>
          A CBOR tag for TRIP breadcrumbs and epochs.
        </li>
        <li>
          A media type registration for application/trip+cbor.
        </li>
        <li>
          An entry in a TBD TRIP entity class registry.
        </li>
      </ul>
    </section>

  </middle>

  <back>

    <!-- ============================================================ -->
    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>

        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>

        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>

        <reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032">
          <front>
            <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
            <date month="January" year="2017"/>
          </front>
          <seriesInfo name="RFC" value="8032"/>
          <seriesInfo name="DOI" value="10.17487/RFC8032"/>
        </reference>

        <reference anchor="RFC6234" target="https://www.rfc-editor.org/info/rfc6234">
          <front>
            <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
            <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake"/>
            <author fullname="T. Hansen" initials="T." surname="Hansen"/>
            <date month="May" year="2011"/>
          </front>
          <seriesInfo name="RFC" value="6234"/>
          <seriesInfo name="DOI" value="10.17487/RFC6234"/>
        </reference>

        <reference anchor="RFC8949" target="https://www.rfc-editor.org/info/rfc8949">
          <front>
            <title>Concise Binary Object Representation (CBOR)</title>
            <author fullname="C. Bormann" initials="C." surname="Bormann"/>
            <author fullname="P. Hoffman" initials="P." surname="Hoffman"/>
            <date month="December" year="2020"/>
          </front>
          <seriesInfo name="STD" value="94"/>
          <seriesInfo name="RFC" value="8949"/>
          <seriesInfo name="DOI" value="10.17487/RFC8949"/>
        </reference>

        <reference anchor="RFC8610" target="https://www.rfc-editor.org/info/rfc8610">
          <front>
            <title>Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures</title>
            <author fullname="H. Birkholz" initials="H." surname="Birkholz"/>
            <author fullname="C. Vigano" initials="C." surname="Vigano"/>
            <author fullname="C. Bormann" initials="C." surname="Bormann"/>
            <date month="June" year="2019"/>
          </front>
          <seriesInfo name="RFC" value="8610"/>
          <seriesInfo name="DOI" value="10.17487/RFC8610"/>
        </reference>

      </references>

      <references>
        <name>Informative References</name>

        <reference anchor="H3" target="https://h3geo.org/docs/">
          <front>
            <title>H3: A Hexagonal Hierarchical Geospatial Indexing System</title>
            <author>
              <organization>Uber Technologies</organization>
            </author>
            <date year="2018"/>
          </front>
        </reference>

        <reference anchor="PARISI" target="https://doi.org/10.1103/RevModPhys.91.030501">
          <front>
            <title>Mean-field theory of spin-glasses with finite coordination number</title>
            <author fullname="Giorgio Parisi" initials="G." surname="Parisi"/>
            <date year="1987"/>
          </front>
        </reference>

        <reference anchor="HAVERSINE" target="https://en.wikipedia.org/wiki/Haversine_formula">
          <front>
            <title>Haversine Formula</title>
            <author>
              <organization>Wikipedia</organization>
            </author>
            <date year="2024"/>
          </front>
        </reference>

      </references>
    </references>

    <!-- ============================================================ -->
    <section anchor="examples" numbered="true" toc="include">
      <name>Example Breadcrumb (Informative)</name>
      <t>
        The following is a JSON representation of a breadcrumb for
        illustration.  The canonical wire format is CBOR as specified
        in <xref target="cbor-encoding"/>.
      </t>
      <sourcecode type="json"><![CDATA[
{
  "index": 42,
  "identity": "3b6a27bcceb6a42d62a3a8d02a6f0d73...",
  "timestamp": "2026-01-15T14:32:10Z",
  "cell": "8a2a1072b59ffff",
  "resolution": 10,
  "context": "e3b0c44298fc1c149afbf4c8996fb924...",
  "previous": "a7ffc6f8bf1ed766...previous_hash...",
  "meta": {
    "battery": 72,
    "accuracy": 8.5,
    "network": "wifi",
    "entity_class": "human",
    "manual": false
  },
  "signature": "9d61b19deffd5a60ba844af49...sig..."
}
      ]]></sourcecode>
    </section>

    <!-- ============================================================ -->
    <section anchor="design-rationale" numbered="true" toc="include">
      <name>Design Rationale (Informative)</name>

      <section anchor="why-h3" numbered="true" toc="include">
        <name>Why H3 Over Other Geospatial Systems</name>
        <t>
          The H3 system was selected over alternatives (S2, Geohash,
          Plus Codes) for several reasons: uniform cell area at each
          resolution level (hexagons tile more evenly than
          rectangles), hierarchical parent-child relationships
          enabling multi-resolution disclosure, efficient neighbor
          computation for velocity checking, and open-source
          availability with well-maintained libraries across
          platforms.
        </t>
      </section>

      <section anchor="why-cbor" numbered="true" toc="include">
        <name>Why CBOR Over JSON</name>
        <t>
          CBOR provides deterministic encoding essential for
          reproducible signature computation, compact binary
          representation suitable for constrained devices and
          bandwidth-limited networks, and native byte string support
          for cryptographic material.  JSON remains useful for
          debugging and human-readable interchange but lacks
          deterministic encoding rules.
        </t>
      </section>

      <section anchor="why-not-biometrics" numbered="true" toc="include">
        <name>Why Trajectory Over Biometrics</name>
        <t>
          Biometric systems capture immutable characteristics
          (fingerprints, iris, face).  Once compromised, the
          credential cannot be rotated.  Biometric databases are
          high-value targets.  Deepfake technology increasingly
          undermines facial recognition.  In contrast, a trajectory
          is: continuously renewable (new movement generates new
          evidence), inherently distributed (no central biometric
          database), resistant to digital fabrication (requires
          physical presence in the real world), and privacy-
          preserving by design (quantized spatial cells, not raw
          coordinates).
        </t>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="acknowledgements" numbered="false" toc="include">
      <name>Acknowledgements</name>
      <t>
        The TRIP protocol builds upon foundational work in
        cryptographic identity systems, geospatial indexing, and
        percolation theory.  The author thanks the contributors to
        the H3 geospatial system, the Ed25519 specification authors,
        and the broader IETF community for establishing the standards
        that TRIP builds upon.
      </t>
    </section>

  </back>
</rfc>
