Skip to documentation
SLOP

tiny.reticulum.destination.cipher

Reference tiny.reticulum destination cipher

Defined in destination.

API (14)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Called byCallstest sourcelib.reticulum.src.destination.test.test_Retic...py:596-665 data-group-hop-1 cipher co...test sourcelib.reticulum.src.destination.test.test_Retic...py:596-665 data-single-hop-0 cipher c...test sourcelib.reticulum.src.destination.testtest: destination cipher copies plain...private sourcelib.reticulum.src.node.inbounddecryptDataprivate sourcelib.reticulum.src.destination.ciphercopyprivate sourcelib.reticulum.src.destination.cipherdecryptGroupidentity.cipherdecryptdestination.cipherdecrypt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.reticulum.src.destination.test.test_Retic...py:596-665 data-group-hop-1 cipher co...test sourcelib.reticulum.src.destination.test.test_Retic...py:596-665 data-single-hop-0 cipher c...test sourcelib.reticulum.src.destination.test.test_Retic...py:106 encrypted MDU boundarytest sourcelib.reticulum.src.destination.testtest: destination cipher copies plain...private sourcelib.reticulum.src.node.outboundencryptPayloadprivate sourcelib.reticulum.src.node.outboundencryptSinglecrypto.token.Tokenencryptcrypto.token.Tokeninitprivate sourcelib.reticulum.src.destination.ciphercopyidentity.cipherencryptdestination.cipherencrypt
Static calls · unresolved targets: 0 · external targets: 1.

Source: lib/reticulum/src/destination/cipher.zig

zig
const std = @import("std");const reticulum = @import("../root.zig");const crypto = reticulum.crypto;const destination = reticulum.destination;const identity = reticulum.identity;/// 383 bytes, the most plaintext one packet to a single-identity destination/// carries, which the reference fixes as/// `floor((464 - 48 - 32) / 16) * 16 - 1`, so a caller sizes the payload it can/// send to one identity, following Reticulum@1.5.0 RNS/Packet.py:106.pub const encrypted_mdu: u16 = 383;/// 464 bytes, the most payload a packet to a plain destination carries, so a/// caller sizes the payload it can send to a plain destination, following/// Reticulum@1.5.0 RNS/Packet.py:110 and Reticulum@1.5.0/// RNS/Reticulum.py:148-155.pub const plain_mdu: u16 = reticulum.wire.mtu - reticulum.wire.header_two_bytes - 1;pub const SingleEncrypt = struct {    public: *const identity.Public,    ratchet_public: ?*const [32]u8,    ephemeral_private: *const [32]u8,    iv: [crypto.token.iv_length]u8,};pub const GroupEncrypt = struct {    key: *const [64]u8,    iv: [crypto.token.iv_length]u8,};pub const EncryptKeys = union(destination.Type) {    single: SingleEncrypt,    group: GroupEncrypt,    plain: void,    link: void,};pub const SingleDecrypt = struct {    private: *const identity.Private,    ratchets: []const identity.Ratchet,    enforce_ratchets: bool,};pub const GroupDecrypt = struct {    key: *const [64]u8,};pub const DecryptKeys = union(destination.Type) {    single: SingleDecrypt,    group: GroupDecrypt,    plain: void,    link: void,};pub const EncryptError = identity.cipher.EncryptError || error{Unsupported};pub const DecryptError = identity.cipher.DecryptError || error{Unsupported};pub const Encrypted = struct {    ciphertext: []u8,    ratchet_id: ?[reticulum.hash.name_bytes]u8,};pub const Decrypted = struct {    plaintext: []u8,    ratchet_id: ?[reticulum.hash.name_bytes]u8,};fn copy(input: []const u8, out: []u8) error{OutputTooSmall}![]u8 {    if (out.len < input.len) return error.OutputTooSmall;    @memmove(out[0..input.len], input);    return out[0..input.len];}/// Seals a payload into `out` by the kind of destination the keys name, so a/// caller seals for whichever kind it is sending to without writing the choice/// out itself, and reports the rotating key it used when it used one, following/// Reticulum@1.5.0 RNS/Destination.py:596-617. A plain destination takes a copy/// of the payload, a single-identity destination takes the ephemeral-key/// exchange, and a group takes a sealed token under the shared 64-byte key./// Sending to a link returns `error.Unsupported`, because a link seals its/// payloads with the key the two ends already agreed on. The call returns/// `error.OutputTooSmall` when `out` is shorter than the result, and the errors/// the single-identity path raises.pub fn encrypt(keys: EncryptKeys, plaintext: []const u8, out: []u8) EncryptError!Encrypted {    return switch (keys) {        .plain => .{ .ciphertext = try copy(plaintext, out), .ratchet_id = null },        .single => |single| blk: {            const ciphertext = try identity.cipher.encrypt(                single.public,                single.ratchet_public,                single.ephemeral_private,                single.iv,                plaintext,                out,            );            const ratchet_id = if (single.ratchet_public) |public|                reticulum.hash.name(public)            else                null;            break :blk .{ .ciphertext = ciphertext, .ratchet_id = ratchet_id };        },        .group => |group| blk: {            const token = crypto.token.Token.init(group.key) catch unreachable;            const ciphertext = try token.encrypt(group.iv, plaintext, out);            break :blk .{ .ciphertext = ciphertext, .ratchet_id = null };        },        .link => error.Unsupported,    };}fn decryptGroup(group: GroupDecrypt, ciphertext: []const u8, out: []u8) DecryptError![]u8 {    const token = crypto.token.Token.init(group.key) catch unreachable;    return token.decrypt(ciphertext, out) catch |err| switch (err) {        error.OutputTooSmall => error.OutputTooSmall,        else => error.InvalidToken,    };}/// Opens a payload into `out` by the kind of destination the keys name, so a/// caller opens an arriving payload by the kind it was addressed to, and/// reports the rotating key that opened it when one did, following/// Reticulum@1.5.0 RNS/Destination.py:622-665. A plain destination takes a copy/// of the payload, a single-identity destination walks its retained keys and/// then its identity key, and a group opens a sealed token under the shared/// 64-byte key. A payload addressed to a link returns `error.Unsupported`. A/// group payload that fails its tag check returns `error.InvalidToken`.pub fn decrypt(keys: DecryptKeys, ciphertext: []const u8, out: []u8) DecryptError!Decrypted {    return switch (keys) {        .plain => .{ .plaintext = try copy(ciphertext, out), .ratchet_id = null },        .single => |single| blk: {            const result = try identity.cipher.decrypt(                single.private,                single.ratchets,                single.enforce_ratchets,                ciphertext,                out,            );            break :blk .{                .plaintext = result.plaintext,                .ratchet_id = result.ratchet_id,            };        },        .group => |group| .{            .plaintext = try decryptGroup(group, ciphertext, out),            .ratchet_id = null,        },        .link => error.Unsupported,    };}comptime {    std.debug.assert(plain_mdu == 464);}

Source: lib/reticulum/src/destination/root.zig:58

zig
pub const cipher = @import("cipher.zig");

Audit

Definitions15
Public names15
Members22
Version26.7.0
Revisiondaab053ee433