Skip to content

Commit

Permalink
style: little tidies
Browse files Browse the repository at this point in the history
  • Loading branch information
codahale committed Nov 19, 2023
1 parent d043003 commit 10e8e47
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 22 deletions.
16 changes: 9 additions & 7 deletions design.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ The basic unit of Lockstitch is the protocol, which encapsulates a transcript of

A Lockstitch protocol supports the following operations:

* `Init`, which initializes a protocol with a domain separation string.
* `Mix`, which adds a labeled input to the protocol's transcript.
* `Derive`, which ratchets the protocol's transcript, preventing rollback, and generates a bitstring
of arbitrary length that is cryptographically dependent on the protocol's prior transcript.
* `Encrypt`/`Decrypt`, which encrypt and decrypt a message, adding an authentication tag of the
* `Init`: Initialize a protocol with a domain separation string.
* `Mix`: Add a labeled input to the protocol's transcript, making all future outputs
cryptographically dependent on it.
* `Derive`: Ratchet the protocol's transcript, preventing rollback, and generate a pseudo-random
bitstring of arbitrary length that is cryptographically dependent on the protocol's prior
transcript.
* `Encrypt`/`Decrypt`: Encrypt and decrypt a message, adding an authentication tag of the
ciphertext to the protocol transcript.
* `Seal`/`Open`, which encrypt and decrypt a message, using an authenticator tag to ensure the
ciphertext has not been modified.
* `Seal`/`Open`: Encrypt and decrypt a message, using an authenticator tag to ensure the ciphertext
has not been modified.

Labels are used for all Lockstitch operations (except `Init`) to provide domain separation of inputs
and outputs. This ensures that semantically distinct values with identical encodings (e.g. public
Expand Down
40 changes: 25 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ impl Protocol {
let mut protocol = Protocol { transcript: Sha256::new() };

// Append the Init op header to the transcript with the domain as the label.
//
// 0x01 || left_encode(|domain|) || domain
protocol.op_header(OpCode::Init, domain.as_bytes());

protocol
Expand All @@ -48,11 +50,13 @@ impl Protocol {
#[inline]
pub fn mix(&mut self, label: &[u8], input: &[u8]) {
// Append a Mix op header with the label to the transcript.
//
// 0x02 || left_encode(|label|) || label
self.op_header(OpCode::Mix, label);

// Append the input to the transcript with right-encoded length.
//
// input || right_encode(|input|)
// input || right_encode(|input|)
self.transcript.update(input);
self.transcript.update(right_encode(&mut [0u8; 17], input.len() as u128 * 8));
}
Expand All @@ -74,6 +78,8 @@ impl Protocol {
#[inline]
pub fn derive(&mut self, label: &[u8], out: &mut [u8]) {
// Append a Derive op header with the label to the transcript.
//
// 0x03 || left_encode(|label|) || label
self.op_header(OpCode::Derive, label);

// Calculate the hash of the transcript and replace it with an empty transcript.
Expand Down Expand Up @@ -102,6 +108,8 @@ impl Protocol {
#[inline]
pub fn encrypt(&mut self, label: &[u8], in_out: &mut [u8]) {
// Append a Crypt op header with the label to the transcript.
//
// 0x04 || left_encode(|label|) || label
self.op_header(OpCode::Crypt, label);

// Derive an AEGIS-128L key and nonce.
Expand All @@ -123,6 +131,8 @@ impl Protocol {
#[inline]
pub fn decrypt(&mut self, label: &[u8], in_out: &mut [u8]) {
// Append a Crypt op header with the label to the transcript.
//
// 0x04 || left_encode(|label|) || label
self.op_header(OpCode::Crypt, label);

// Derive an AEGIS-128L key and nonce.
Expand All @@ -149,6 +159,8 @@ impl Protocol {
let (in_out, tag) = in_out.split_at_mut(in_out.len() - TAG_LEN);

// Append an AuthCrypt op header with the label to the transcript.
//
// 0x05 || left_encode(|label|) || label
self.op_header(OpCode::AuthCrypt, label);

// Perform a Crypt operation with the plaintext.
Expand All @@ -167,6 +179,8 @@ impl Protocol {
let (in_out, tag) = in_out.split_at_mut(in_out.len() - TAG_LEN);

// Append an AuthCrypt op header with the label to the transcript.
//
// 0x05 || left_encode(|label|) || label
self.op_header(OpCode::AuthCrypt, label);

// Perform a Crypt operation with the ciphertext.
Expand Down Expand Up @@ -225,19 +239,23 @@ impl Protocol {
/// Append an operation header with an optional label to the protocol transcript.
#[inline]
fn op_header(&mut self, op_code: OpCode, label: &[u8]) {
// Append the operation code to the transcript:
// Append the operation code and label to the transcript:
//
// op_code
// op_code || left_encode(|label|) || label
self.transcript.update([op_code as u8]);

// Append the label to the transcript:
//
// left_encode(|label|) || label
self.transcript.update(left_encode(&mut [0u8; 17], label.len() as u128 * 8));
self.transcript.update(label);
}
}

/// Compare two slices for equality in constant time.
#[inline]
pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
let mut res = 1;
a.cmovne(b, 0, &mut res);
res != 0
}

/// Derive a KDF key and additional output from [NIST SP 800-56C Rev. 2][]'s _One-Step Key
/// Derivation_ with SHA-256.
///
Expand Down Expand Up @@ -273,14 +291,6 @@ fn concat_kdf(ikm: &[u8], kdf_key: &mut [u8; 32], out: &mut [u8]) {
}
}

/// Compare two slices for equality in constant time.
#[inline]
pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
let mut res = 1;
a.cmovne(b, 0, &mut res);
res != 0
}

/// All Lockstitch operation types.
#[derive(Debug, Clone, Copy)]
enum OpCode {
Expand Down

0 comments on commit 10e8e47

Please sign in to comment.