6.1 KiB
6.1 KiB
Multi-User OTP Partitioning Parity & Enhancement Plan
Overview
The multi-user / multi-device OTP dynamic partitioning scheme (OTP-GRANT-V1, end_offset, next_extent, and passive peer_extent tracking in a single <chksum>.state file) is partially implemented in signer, but has several protocol parity gaps compared to ~/lt/otp (src/pads.c and src/crypto.c), as well as missing RPC and TUI integration.
sequenceDiagram
participant Donor as Donor Device - otp or signer
participant StateA as Donor .state
participant Recip as Recipient - signer
participant StateB as Recipient .state
Donor->>Donor: mid = align_256((offset + end) / 2)
Donor->>StateA: Write end_offset=mid & peer_extent=mid+256:old_end + fsync
Donor->>Donor: Encrypt OTP-GRANT-V1 at offset mid (256B)
Donor->>Recip: Send -----BEGIN OTP MESSAGE-----
Recip->>Recip: Decrypt chunk at mid & verify Pad-ChkSum
Recip->>Recip: Check no overlap with [offset, end_offset)
Recip->>StateB: Adopt immediately (if new/exhausted) or push next_extent + fsync
1. Core Protocol & Safety Fixes in src/otp_pad.rs
-
Validate
Pad-ChkSuminparse_grant_message:- Update
parse_grant_message(plaintext: &[u8]) -> Option<(String, u64, u64)>to require and return thePad-ChkSum: <64hex>header (matchingparse_grant_messagein~/lt/otp/src/pads.c). - In
OtpPadState::decrypt_encoded, verifygrant_chksum == self.chksumbefore applying the grant; returnErr(SignerError::InvalidInput)on mismatch.
- Update
-
Harden Grant Import (
apply_grantlogic indecrypt_encoded):- Overlap check: If the state file already exists, reject any grant where
start < self.partition_end() && self.offset < end(Err(SignerError::InvalidInput)), matchingapply_grant_to_statein~/lt/otp/src/pads.c. - Immediate adoption on exhausted partition: If
self.offset >= self.partition_end() && self.next_extents.is_empty(), immediately setself.offset = startandself.end_offset = Some(end)instead of pushing tonext_extents. - Bounds check: When queueing into
self.next_extents, enforceself.next_extents.len() < MAX_NEXT_EXTENTS(returnErr(SignerError::InvalidInput)if full).
- Overlap check: If the state file already exists, reject any grant where
-
Crash-Safe Persistence (
fsync):- In
OtpPadState::persist_state, open/create the.tmpfile, write the state content, callfile.sync_all(), close it, and thenstd::fs::renameover<chksum>.state. This guarantees the shrunkenend_offsetis on disk before any grant message is emitted.
- In
-
Extended
.stateSupport inscan_padsandPadInfo:- Expand
PadInfoto includeend_offset: Option<u64>,next_count: usize,peer_count: usize, and a helperpartition_status(&self) -> Stringthat formats"whole","1/2","2/3+q", etc. (matchingformat_partition_statusin~/lt/otp/src/pads.c). - Fix
scan_padsto callparse_state_fileinstead ofs.trim().parse::<u64>()so.statefiles withoffset=<N>and multi-line extents report accurate offsets and partition status.
- Expand
-
Global Status & Global Split Entry Point:
- Update
OtpPadStateandglobal_status()to display the active partition upper bound (offset/end_offset (part 1/2)) rather than onlyoffset/pad_size. - Add
pub struct OtpSplitOutput { pub pad_chksum: String, pub grant_start: u64, pub grant_end: u64, pub new_end_offset: u64, pub grant_armor: String }andpub fn global_split() -> Result<OtpSplitOutput, SignerError>which callssplit_partition(),format_grant_message(), andencrypt_encoded_at(grant.start - 256, ...).
- Update
2. JSON-RPC & Server Support (src/enforcement.rs, src/dispatcher.rs, src/server.rs)
VERB_SPLITConstant & Routing:- Add
pub const VERB_SPLIT: &str = "split";insrc/enforcement.rs. - In
src/dispatcher.rs:- Route
VERB_SPLIT(whenoptions.algorithm == "otp"or no other algorithm is specified) tohandle_otp_verb. - Include
"split"inget_infoverbs list. - Implement
VERB_SPLITinhandle_otp_verbcallingcrate::otp_pad::global_split()and returning:{ "grant": "<ascii-armored OTP-GRANT-V1>", "pad_chksum": "<64hex>", "grant_start": 2304, "grant_end": 4096, "end_offset": 2048 }
- Route
- In
src/server.rs, allowVERB_SPLITalongsideVERB_ENCRYPTandVERB_DECRYPTinprocess_request.
- Add
3. TUI Updates (src/tui.rs)
- OTP Pad Browser (
RoleAddStage::OtpBrowse):- Display both partition usage and partition status (
whole,1/2,1/2+q) fromPadInfowhen browsing pads.
- Display both partition usage and partition status (
- Main Screen Connections Panel:
- Automatically reflects the richer
global_status()showing partition bounds and peer/queued counts.
- Automatically reflects the richer
4. signer-client Updates (src/client/)
- Fix
end_offsetOutput Bug insrc/client/main.rs:- In
run_split, fix line 627 fromprintln!("This device's new end_offset: {}", grant.start);togrant.start - 256(matchingotp.partition_end()and~/lt/otp/src/pads.c).
- In
- Support Daemon RPC Split:
- Add
otp_split(&mut self, alg: &AlgOptions)toSignerSignerinsrc/client/signer.rs. - In
src/client/cli.rsandsrc/client/main.rs, allowsigner-client -a otp split(orsigner-client split --remote) to invoke thesplitRPC verb against the runningsignerdaemon's bound pad, while keepingsigner-client split <pad-prefix>for direct local pad splitting.
- Add
5. Tests (src/otp_pad.rs, src/dispatcher.rs)
- Update existing unit tests in
src/otp_pad.rsfor the 3-tuple return ofparse_grant_message. - Add unit tests for:
- Rejecting a grant with a mismatched
Pad-ChkSum. - Rejecting a grant that overlaps the active
[offset, end_offset)partition. - Immediate adoption of a grant when the current partition is exhausted (
offset == end_offset). - Rejecting grants beyond
MAX_NEXT_EXTENTS. scan_padsparsingoffset=512,end_offset=...,next_extent=..., andpeer_extent=....
- Rejecting a grant with a mismatched
- Add dispatcher unit test
test_otp_split_and_grant_import_roundtripinsrc/dispatcher.rs.