tiny.reticulum.destination.cipher
Defined in destination.
API (14)
Actions
Public operations.
decrypt: Opens a payload intooutby 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.encrypt: Seals a payload intooutby 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.
Types and contracts
Public types and contracts.
DecryptErrorDecryptKeysDecryptedEncryptErrorEncryptKeysEncryptedGroupDecryptGroupEncryptSingleDecryptSingleEncrypt
Values and defaults
Public values and defaults.
encrypted_mdu: 383 bytes, the most plaintext one packet to a single-identity destination carries, which the reference fixes asfloor((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.plain_mdu: 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.
Source
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
| Definitions | 15 |
|---|---|
| Public names | 15 |
| Members | 22 |
| Version | 26.7.0 |
| Revision | daab053ee433 |