Skip to documentation
SLOP

tiny.reticulum.identity

Reference tiny.reticulum identity

Defined in tiny.reticulum.

The key material behind one Reticulum address and everything that material does: name itself, sign, check a signature, seal a payload for a peer, open what arrives, and roll a short-lived key forward.

API (29)

Actions

Public operations.

Types and contracts

Public types and contracts.

Namespaces

Public namespaces.

Values and defaults

Public values and defaults.

No direct callersNo direct callstiny.reticulumidentity
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/reticulum/src/identity/key.zig:102

zig
/// A view of 64 public bytes the caller already holds, which hashes and checks/// signatures where the bytes lie. The view copies nothing, so the bytes it/// points at have to outlive it.pub const BorrowedPublic = struct {    bytes: *const KeyBytes,    pub fn fromBytes(bytes: *const KeyBytes) BorrowedPublic {        return .{ .bytes = bytes };    }    pub fn toBytes(self: BorrowedPublic) KeyBytes {        return self.bytes.*;    }    /// Returns the first 16 bytes of the SHA-256 digest of the 64 public bytes,    /// which names the identity inside a destination name, following    /// Reticulum@1.5.0 RNS/Identity.py:784-786.    pub fn hash(self: BorrowedPublic) [reticulum.hash.truncated_bytes]u8 {        return reticulum.hash.truncated(self.bytes[0..key_bytes]);    }    /// Returns whether an Ed25519 signature over a message checks out under the    /// identity's signing half, following Reticulum@1.5.0 RNS/Identity.py:925.    /// Public bytes that form no valid Ed25519 point give false.    pub fn validate(self: BorrowedPublic, signature: [64]u8, message: []const u8) bool {        const signing = Ed25519.PublicKey.fromBytes(            self.bytes[half_bytes..key_bytes].*,        ) catch return false;        const encoded = Ed25519.Signature.fromBytes(signature);        encoded.verify(message, signing) catch return false;        return true;    }};

Source: lib/reticulum/src/identity/key.zig:22

zig
/// The 64 private bytes behind one identity, an X25519 secret followed by an/// Ed25519 seed, following Reticulum@1.5.0/// RNS/Identity.py:59-62,624,727,737-754. The public bytes, the identity hash,/// and every signature derive from these. The value holds the bytes inline, so/// a copy is a second copy of the secret, and the caller that wants them gone/// keeps one instance and erases it.pub const Private = struct {    bytes: KeyBytes,    pub fn fromBytes(bytes: KeyBytes) Private {        return .{ .bytes = bytes };    }    pub fn zero(self: *Private) void {        std.crypto.secureZero(u8, &self.bytes);    }    pub fn toBytes(self: *const Private) KeyBytes {        return self.bytes;    }    pub fn publicBytes(self: *const Private) KeyBytes {        const encryption = X25519.recoverPublicKey(self.bytes[0..half_bytes].*) catch            unreachable;        const signing = Ed25519.KeyPair.generateDeterministic(            self.bytes[half_bytes..key_bytes].*,        ) catch unreachable;        var result: KeyBytes = undefined;        result[0..half_bytes].* = encryption;        result[half_bytes..key_bytes].* = signing.public_key.toBytes();        return result;    }    pub fn public(self: *const Private) Public {        return Public.fromBytes(self.publicBytes());    }    pub fn hash(self: *const Private) [reticulum.hash.truncated_bytes]u8 {        return reticulum.hash.truncated(&self.publicBytes());    }    pub fn sign(self: *const Private, message: []const u8) [64]u8 {        const signing = Ed25519.KeyPair.generateDeterministic(            self.bytes[half_bytes..key_bytes].*,        ) catch unreachable;        const signature = signing.sign(message, null) catch unreachable;        return signature.toBytes();    }};

Source: lib/reticulum/src/identity/key.zig:71

zig
/// The 64 public bytes of one identity, an X25519 public key followed by an/// Ed25519 public key, following Reticulum@1.5.0/// RNS/Identity.py:59-62,730-735,766-778. The value holds the bytes inline, so/// a copy is a second copy, and the caller that wants them gone keeps one/// instance and erases it.pub const Public = struct {    bytes: KeyBytes,    pub fn fromBytes(bytes: KeyBytes) Public {        return .{ .bytes = bytes };    }    pub fn zero(self: *Public) void {        std.crypto.secureZero(u8, &self.bytes);    }    pub fn toBytes(self: *const Public) KeyBytes {        return self.bytes;    }    pub fn borrowed(self: *const Public) BorrowedPublic {        return BorrowedPublic.fromBytes(&self.bytes);    }    pub fn hash(self: *const Public) [reticulum.hash.truncated_bytes]u8 {        return self.borrowed().hash();    }    pub fn validate(self: *const Public, signature: [64]u8, message: []const u8) bool {        return self.borrowed().validate(signature, message);    }};
Called byCallsNo direct callsidentity.Publicborrowedidentity.BorrowedPublicfromBytes
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/reticulum/src/identity/key.zig:14

zig
pub const KeyBytes = [key_bytes]u8;
Called byCallsNo direct callersidentity.PrivatepublicBytesidentity.Privatehash
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersidentity.PrivatepublicBytesidentity.PublicfromBytesidentity.Privatepublic
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsidentity.Privatehashidentity.Privatepublicidentity.PrivatepublicBytes
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallsidentity.Publichashidentity.Publicvalidateidentity.BorrowedPublicfromBytesidentity.Publicborrowed
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsidentity.Privatepublicidentity.PublicfromBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersidentity.Publicborrowedidentity.Publichash
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersidentity.Publicborrowedidentity.Publicvalidate
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/reticulum/src/identity/key.zig:10

zig
/// 64 bytes, the width of a Reticulum key value, which holds an X25519 half/// followed by an Ed25519 half, following Reticulum@1.5.0/// RNS/Identity.py:59-62.pub const key_bytes: usize = 64;

Source: lib/reticulum/src/identity/root.zig

zig
//! The key material behind one Reticulum address and everything that material//! does: name itself, sign, check a signature, seal a payload for a peer, open//! what arrives, and roll a short-lived key forward. An address on this network//! is a hash over a dotted name and the owner's public key, so the keys here//! make an address reachable by its owner alone.//!//! Whoever holds these bytes has to be the only party that can read what is//! addressed to the name and the only one that can sign for it. The code runs//! where memory is fixed before the program starts, so key values are plain//! arrays and every store takes its size from the caller. A node also has to//! remember what it learned about other parties from their announcements, under//! the same fixed memory.//!//! Key bytes that travel by value leave copies the owner has no way to reach,//! so erasing one copy leaves the rest. One key pair that never changes leaves//! every message ever addressed to it readable once those bytes leak. The//! sender picks which of a party's keys it encrypts to, so the receiver has to//! work out which one was used before it can read anything.//!//! The subtree follows Reticulum 1.5.0, the reference implementation, pinned to//! one upstream commit by the package README and the generated conformance//! corpus. What it takes is the key layout of Reticulum@1.5.0//! RNS/Identity.py:59-62, the encryption transcript of Reticulum@1.5.0//! RNS/Identity.py:804-836, the decryption order of Reticulum@1.5.0//! RNS/Identity.py:849-907, and the rotation rule of Reticulum@1.5.0//! RNS/Destination.py:206-243. The package generates identity vectors from that//! release and replays them in tests, so each of those claims is checkable from//! this tree.//!//! A party's key material, private or public (*identity*), is one 64-byte value//! the caller owns, and a caller that needs the bytes gone keeps a single//! instance and erases it in place. A third form borrows 64 public bytes the//! caller already holds, so checking a received announcement needs no copy of//! the key out of the payload. The short-lived keys a party has published//! (*rotating keys*) live newest first in one block of caller storage, which is//! zeroed when it is taken and again when it is handed back. Decryption walks//! the rotating keys a party keeps after it stops publishing them (*retained//! keys*) in the order the caller gave, falls back to the identity key, and//! reports which retained key opened the message. Every shared secret and//! derived key is erased before the call that made it returns. The subtree//! names its pieces: the key pairs, encryption and decryption, rotating keys//! and the ring that holds them, and what the node remembers about other//! parties.const key = @import("key.zig");const ratchet_module = @import("ratchet.zig");pub const Private = key.Private;pub const Public = key.Public;pub const BorrowedPublic = key.BorrowedPublic;pub const key_bytes = key.key_bytes;pub const KeyBytes = key.KeyBytes;pub const Rotating = @import("rotating.zig").Rotating;pub const cipher = @import("cipher.zig");pub const ratchet = ratchet_module;pub const Ratchet = ratchet_module.Ratchet;pub const Ring = ratchet_module.Ring;pub const Seconds = ratchet_module.Seconds;pub const known = @import("known.zig");

Source: lib/reticulum/src/root.zig:63

zig
pub const identity = @import("identity/root.zig");

Audit

Definitions23
Public names23
Members3
Version26.7.0
Revisiondaab053ee433