Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations in complex protocols.

Overview

Lockstitch

Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations (e.g. hashing, encryption, message authentication codes, and authenticated encryption) in complex protocols. Inspired by TupleHash, STROBE, Noise Protocol's stateful objects, and Xoodyak's Cyclist mode, Lockstitch combines BLAKE3 and ChaCha8 to provide GiB/sec performance on modern processors at a 128-bit security level.

⚠️ WARNING: You should not use this. ⚠️

Neither the design nor the implementation of this library have been independently evaluated.

Design

A Lockstitch protocol is a stateful object which has five different operations:

  • Mix: Mixes a piece of data into the protocol's state, making all future outputs dependent on it.
  • Derive: Outputs bytes of pseudo-random data dependent on the protocol's prior state.
  • Encrypt/Decrypt: Encrypts and decrypts data using the protocol's state as the key.
  • Tag/CheckTag: Generates and verifies authenticator tags of the protocol's state.
  • Ratchet: Irreversibly modifies the protocol's state, preventing rollback.

Using these operations, one can construct a wide variety of symmetric-key constructions.

Use

Lockstitch is used to compose cryptographic protocols.

For example, we can create message digests:

fn digest(data: &[u8]) -> [u8; 32] {
  let mut md = lockstitch::Protocol::new("com.example.md");
  md.mix(data);
  md.derive_array()
}

assert_eq!(digest(b"this is a message"), digest(b"this is a message"));
assert_ne!(digest(b"this is a message"), digest(b"this is another message"));

We can create message authentication codes:

fn mac(key: &[u8], data: &[u8]) -> [u8; 16] {
  let mut mac = lockstitch::Protocol::new("com.example.mac");
  mac.mix(key);
  mac.mix(data);
  mac.tag_array()
}

assert_eq!(mac(b"a key", b"a message"), mac(b"a key", b"a message"));

We can even create authenticated encryption:

Option> { let (ciphertext, tag) = ciphertext.split_at(ciphertext.len() - lockstitch::TAG_LEN); let mut plaintext = ciphertext.to_vec(); let mut aead = lockstitch::Protocol::new("com.example.aead"); aead.mix(key); aead.mix(nonce); aead.mix(ad); aead.decrypt(&mut plaintext); aead.check_tag(tag).then_some(plaintext) } let plaintext = b"a message".to_vec(); let ciphertext = aead_encrypt(b"a key", b"a nonce", b"some data", &plaintext); assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some data", &ciphertext), Some(plaintext)); assert_eq!(aead_decrypt(b"another key", b"a nonce", b"some data", &ciphertext), None); assert_eq!(aead_decrypt(b"a key", b"another nonce", b"some data", &ciphertext), None); assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some other data", &ciphertext), None); let mut bad_ciphertext = ciphertext.to_vec(); bad_ciphertext[5] ^= 1; // flip one bit assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some data", &bad_ciphertext), None);">
fn aead_encrypt(key: &[u8], nonce: &[u8], ad: &[u8], plaintext: &[u8]) -> Vec<u8> {
  let mut out = vec![0u8; plaintext.len() + lockstitch::TAG_LEN];
  let (ciphertext, tag) = out.split_at_mut(plaintext.len());
  ciphertext.copy_from_slice(plaintext);

  let mut aead = lockstitch::Protocol::new("com.example.aead");
  aead.mix(key);
  aead.mix(nonce);
  aead.mix(ad);
  aead.encrypt(ciphertext);
  aead.tag(tag);

  out
}

fn aead_decrypt(key: &[u8], nonce: &[u8], ad: &[u8], ciphertext: &[u8]) -> Option<Vec<u8>> {
  let (ciphertext, tag) = ciphertext.split_at(ciphertext.len() - lockstitch::TAG_LEN);
  let mut plaintext = ciphertext.to_vec();

  let mut aead = lockstitch::Protocol::new("com.example.aead");
  aead.mix(key);
  aead.mix(nonce);
  aead.mix(ad);
  aead.decrypt(&mut plaintext);
  aead.check_tag(tag).then_some(plaintext)
}

let plaintext = b"a message".to_vec();
let ciphertext = aead_encrypt(b"a key", b"a nonce", b"some data", &plaintext);
assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some data", &ciphertext), Some(plaintext));
assert_eq!(aead_decrypt(b"another key", b"a nonce", b"some data", &ciphertext), None);
assert_eq!(aead_decrypt(b"a key", b"another nonce", b"some data", &ciphertext), None);
assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some other data", &ciphertext), None);

let mut bad_ciphertext = ciphertext.to_vec();
bad_ciphertext[5] ^= 1; // flip one bit
assert_eq!(aead_decrypt(b"a key", b"a nonce", b"some data", &bad_ciphertext), None);

Cargo Features

  • std: Enables features based on the Rust standard library. Enabled by default.
  • hedge: Enables hedged random value generation with rand_core. Enabled by default.

Performance

Both BLAKE3 and ChaCha8 benefit significantly from the use of SIMD operations, allowing them to process larger inputs and outputs in parallel.

The SIMD optimizations in the blake3 and chacha20 crates require enabling specific CPU features in your build. blake3 has optimizations for AVX2, AVX512, SSE2, and SSE4.1 on Intel CPUs and NEON on ARM CPUs. chacha20 has optimizations for AVX2 and SSE2 on Intel CPUs.

To compile a x86-64 binary with support for AVX2 and SSE2, for example, create a .cargo/config.toml file with the following:

[build]
rustflags = ["-C", "target-features=+avx2,+sse2"]

To compile a non-portable binary which enables all optimizations for the specific CPU on the compiling machine, create a .cargo/config.toml file with the following:

[build]
rustflags = ["-C", "target-cpu=native"]

Additional Information

For more information on the design of Lockstitch, see design.md. For more information on performance, see perf.md.

License

Copyright © 2022 Coda Hale

Distributed under the Apache License 2.0 or MIT License.

You might also like...
 An implementation of the paper
An implementation of the paper "Honey Badger of BFT Protocols" in Rust. This is a modular library of consensus.

Honey Badger Byzantine Fault Tolerant (BFT) consensus algorithm Welcome to a Rust library of the Honey Badger Byzantine Fault Tolerant (BFT) consensus

Two-party and multi-party ECDSA protocols based on class group with Rust

CG-MPC-ECDSA This project aims to implement two-party and multi-party ECDSA protocols based on class group with Rust. It currently includes schemes de

Ingraind - a security monitoring agent built around RedBPF for complex containerized environments and endpoints.
Ingraind - a security monitoring agent built around RedBPF for complex containerized environments and endpoints.

ingraind is a security monitoring agent built around RedBPF for complex containerized environments and endpoints. The ingraind agent uses eBPF probes to provide safe and performant instrumentation for any Linux-based environment.

Fiddi is a command line tool that does the boring and complex process of checking and processing/watching transactions on EVM compatible Blockchain.

Fiddi is a command line tool that does the boring and complex process of checking and processing/watching transactions on EVM compatible Blockchain.

`llm-chain` is a powerful rust crate for building chains in large language models allowing you to summarise text and complete complex tasks

llm-chain 🚀 llm-chain is a collection of Rust crates designed to help you work with Large Language Models (LLMs) more effectively. Our primary focus

Proteus: Programmable Protocols for Censorship Circumvention
Proteus: Programmable Protocols for Censorship Circumvention

Proteus Debug build (also used for tests): cargo build Release build (optimized): cargo build --release Run unit tests: cargo test Run integration

A Rust implementation of the ISO11783 (ISOBUS) & J1939 protocols

AgIsoStack-rs About This Library AgIsoStack-rs is an MIT licensed hardware agnostic ISOBUS (ISO11783) and SAE J1939 CAN stack written in Rust. This pr

Release complex cargo-workspaces automatically with changelog generation, used by `gitoxide`

cargo smart-release Fearlessly release workspace crates and with beautiful semi-handcrafted changelogs. Key Features zero-configuration cargo smart-re

Open Protocol Indexer, OPI, is the best-in-slot open-source indexing client for meta-protocols on Bitcoin.

OPI - Open Protocol Indexer Open Protocol Indexer, OPI, is the best-in-slot open-source indexing client for meta-protocols on Bitcoin. OPI uses a fork

Owner
Coda Hale
A real person.
Coda Hale
Cryptographic Primitive Code Generation by Fiat

Fiat-Crypto: Synthesizing Correct-by-Construction Code for Cryptographic Primitives Building This repository requires Coq 8.11 or later. Note that if

Programming Languages and Verification Group at MIT CSAIL 538 Jan 7, 2023
Meta-repository for Miscreant: misuse-resistant symmetric encryption library with AES-SIV (RFC 5297) and AES-PMAC-SIV support

The best crypto you've never heard of, brought to you by Phil Rogaway A misuse resistant symmetric encryption library designed to support authenticate

miscreant. 480 Dec 8, 2022
Password-Authenticated Key Agreement protocols

RustCrypto: PAKEs Password-Authenticated Key Agreement protocols implementation. Warnings Crates in this repository have not yet received any formal c

Rust Crypto 81 Dec 5, 2022
Key derivation and cryptographic signing functionality for Ethereum applications (ethers-rs)

ethers-signer-factory ethers-signer-factory is a Rust crate that provides functions for key derivation and signing of Ethereum transactions and messag

Ilia 3 Sep 27, 2023
BTM is an incremental data backup mechanism that does not require downtime.

BTM Blockchain Time Machine. BTM is an incremental data backup mechanism that does not require downtime.

漢 2 Mar 27, 2022
Incremental hashing based on curve25519-dalek

A toy project on building an incremental hash function using the Ristretto elliptic curve for me to learn Rust. Example code from examples/main.rs: us

Alin Tomescu 2 Apr 1, 2022
Yi Token by Crate Protocol: the primitive for auto-compounding single token staking pools.

yi Yi Token by Crate Protocol: the primitive for auto-compounding single token staking pools. About Yi is a Solana primitive for building single-sided

Crate Protocol 12 Apr 7, 2022
Avalanche primitive types in Rust (experimental)

AvalancheGo Compatibility Crate Version(s) AvalancheGo Version(s) Protocol Version v0.0.134-155 v1.9.2,v1.9.3 19 v0.0.156-176 v1.9.4 20 v0.0.177-200 v

Ava Labs 26 Feb 4, 2023
Rust implementation of the i2p client/server/router protocols

ri2p Rust implementation of the i2p client/server/router protocols Status Common Commands cargo build: Builds the ri2p binary cargo run: Runs the ri2p

Christopher Bilger 8 Nov 25, 2022
A multiplexed p2p network framework that supports custom protocols

Tentacle Overview This is a minimal implementation for a multiplexed p2p network based on yamux that supports mounting custom protocols. Architecture

漂流 188 Dec 19, 2022