Skip to content
THCLabPublic

About

A Rust implementation of the KERI protocol

Resources

Stars

26 stars

Watchers

5 watching

Forks

Repository files navigation

KERIOX

What is KERIOX in a nutshell?

KERIOX is a Rust implementation of the Decentralized Key Management System (DKMS) that under the hood uses the Key Event Receipt Infrastructure (KERI) protocol.

The Human Colossus Foundation has been developing and maintaining KERIOX since 2020.

Usage

Introduction

KERIOX is an open-source Rust implementation of the Key Event Receipt Infrastructure (KERI) , a system designed to provide a secure identifier-based trust spanning layer for any stack. The current version of the KERI paper can be found here.

KERI provides the same security and verifiability properties for transactions as a blockchain or distributed ledger can, without the overhead of requiring an absolute global ordering of transactions. Because of this, there is no need for a canonical chain and thus there is no "KERI Chain" or "KERI Network". KERI Identifiers can be generated independently in a self-sovereign and privacy-preserving manner and are secured via a self-certifying post-quantum resistant key management scheme based on blinded pre-rotation, auditable and flexible key events and a distributed conflict resolution algorithm called KAACE.

Architecture

KERIOX is designed around pluggable abstractions that allow it to run in diverse environments. The EventDatabase trait abstracts storage so that backends can be swapped at compile time; redb is the default (feature-flagged as storage-redb), and an in-memory implementation is available for testing or custom backends. Notification dispatch is also pluggable via NotificationBus, which supports injectable dispatch strategies suitable for serverless environments such as SQS-backed message routing. The KeriRuntime<D> struct bundles the processor, storage, escrows, and notification bus into a single composable unit, enabling thin Lambda handlers or other lightweight entry points.

Abandoning an identifier

Following the KERI specification, an identifier is abandoned by a rotation (rot, or drt for a delegated identifier) that commits to no next keys (n=[], nt=0); an inception that does so makes it non-transferable instead. Either way its key event log is final and no more key events are allowed in it:

  • Core refuses every later event (Error::AbandonedIdentifier or Error::NonTransferableIdentifier). For an abandoned identifier it also refuses replies, exchanges and transferable receipts signed by it, an extension beyond the specification: abandoning signals that its controller no longer speaks for it. Queries are still answered, so the owner can collect receipts for the abandonment. A non-transferable identifier keeps speaking for itself.
  • As the specification requires, an establishment event's key list k must not be empty, an integer threshold (kt, nt) may not need more keys than its list has, and a weighted one has exactly one weight per key (KERIpy only checks for at most one). So no next keys means nt=0. A key event without a single controller signature is dropped, not escrowed, and answered with 400.
  • Witnesses receipt the abandonment but answer 410 Gone to anything after it.
  • Watchers serve the final log, stop polling the witnesses for it, and answer full-log queries without waiting on them.
  • Both serve GET /identifiers/{aid}/state without authentication: the identifier's sn, last event, witnesses, whether it is transferable and, when abandoned, "abandoned": {"sn", "said"}. It is a hint for operators and fresh clients; whoever relies on it verifies the KEL through an authenticated watcher query. Unknown identifiers get 404.
  • Both list "features": ["abandonment"] on GET /info. Check every witness and watcher before abandoning an identifier: an older one would still receipt or serve events that follow the abandonment.
  • The controller builds the event (Identifier::abandon, abandon_group), and the SDK wraps it (Identity::abandon, KeriStore::abandon, operations::abandon, Keri::remove_identity). The SDK refuses to verify anything signed with an abandoned identifier's final keys.

KERI 1.0 and 2.0

keriox reads KERI 1.0 and KERI 2.0 messages, and writes KERI 1.0 unless told otherwise, so a node or client can be upgraded before its peers.

Versions are the KERI protocol versions of the version string, in the dotted-decimal notation of the CESR specification:

Version Version string Attachments
1.0 KERI10JSON…_ (vv = 10) CESR 1.0 code table (-_AAABAA)
2.0 KERICAACAAJSON…. (protocol CAA = 2.0, genus CAA = 2.0) CESR genus 2.0 code table (-_AAACAA)

Any minor version of protocol 1 or 2 is read by that major's rules; other majors, and 2.x messages on a CESR genus other than 2.x, are refused. These are protocol versions, not the versions of the specification documents.

  • KERI 2.0 key events, receipts, qry, rpy and exn are written with a 2.0 version string and CESR 2.0 attachments. Routed messages (qry, rpy) name their sender in i, and exn carries i, ri, x and p; the sender must be the signer.
  • What a node writes in answer to something follows what it answers: a receipt follows the event's version, a key state notice the query's.
  • The controller writes its own messages in ControllerConfig::keri_version, the SDK in KeriStore::with_keri_version, and witnesses and watchers in keri_version in their configuration file ("1.0" or "2.0"; WITNESS_KERI_VERSION and WATCHER_KERI_VERSION in the environment).
  • Switch a writer to 2.0 only once everything that reads its messages runs a keriox that reads 2.0. Older releases refuse KERI 2.0 messages. Witnesses and watchers that read 2.0 list "keri2" on GET /info (supports_keri2 in the SDK).
  • Witnesses and watchers report what they write on GET /info as "keri": {"protocol": "2.0", "cesr_genus": "2.0"} (server_keri_version in the SDK). Operators switch the servers first; a client that follows them asks agreed_keri_version with the witnesses and watchers it uses, which answers 2.0 only once every one of them writes 2.0 and 1.0 if any writes 1.0 or cannot be reached.
  • keriox clients name their release in every request (User-Agent: keriox/<release>), and witnesses and watchers count requests by it (keri_witness_requests_by_client_total, keri_watcher_requests_by_client_total), so operators can tell when old clients are gone.
  • A witness or watcher with min_client_version set (e.g. "0.20.0"; WITNESS_MIN_CLIENT_VERSION, WATCHER_MIN_CLIENT_VERSION) answers 426 Upgrade Required to every POST from an older keriox client or from a client that names no release. GET requests (/info, OOBIs) stay open.
  • TEL events stay KERI 1.0: the KERI specification defines no TEL messages, and registries in KERI 2.0 come with ACDC 2.0.
  • An identifier incepted in KERI 1.0 moves to a new one with KeriStore::reincept: the new identifier is incepted (in the store's version, with KeriStore::same_witnesses for the same witnesses) and the old one abandoned with a final rotation anchoring the new inception. The SDK follows that seal when it imports a contact (Keri::import_contact_from returns the new identifier, Keri::successor_of records the move).

License

EUPL 1.2

We have distilled the most crucial license specifics to make your adoption seamless: see here for details.

Status

KERIOX implementation is in progress and ongoing. We support all the KERI protocol's significant features and provide the second most advanced implementation right after the keripy reference implementation.

We furthermore support bindings to NodeJS and Dart. See our keri-bindings repository.

Organization

This repository provides the implementation of the KERI protocol. keriox_core brings the core protocol features that are further consumed by the following concepts:

  • Witness: the KERI Witness
  • Watcher: the KERI Watcher
  • Controller: the client for accessing the infrastructure
  • SDK: high-level SDK providing KeriRuntime and Controller for KERI+TEL operations
  • Key Provider: pluggable cryptographic signing abstraction (software, file-encrypted, OS keychain, host-callback for mobile)

Mobile support

KERIOX supports mobile targets (Android API 30+ and iOS) via:

  • mobile feature flag on keri-sdk — enables host + software key providers, uses rustls for TLS
  • HostCallbackKeyProvider in keri_keyprovider — delegates all signing to host platform callbacks (Android Keystore / iOS Keychain). Private keys never enter Rust memory.
  • rustls TLS backend — pure Rust, no OpenSSL dependency
  • redb storage — pure Rust, no mmap, works on both Android and iOS app sandboxes

See the mobile SDK CI workflow for cross-compilation verification.

About

A Rust implementation of the KERI protocol

Resources

Stars

26 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages