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 uses the Rocca-S authenticated cipher and SHA-256 to provide 100+ Gb/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. It uses very recent cryptographic algorithms in slightly heterodox ways and may well be just an absolutely terrible idea. The design is documented in design.md; read it and see if the arguments therein are convincing.

In addition, there is absolutely no guarantee of backwards compatibility.

Design

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

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:

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

asserteq!(digest(b"this is a message"), digest(b"this is a message")); assertne!(digest(b"this is a message"), digest(b"this is another message")); ```

We can create message authentication codes:

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

asserteq!(mac(b"a key", b"a message"), mac(b"a key", b"a message")); assertne!(mac(b"a key", b"a message"), mac(b"another key", b"a message")); assert_ne!(mac(b"a key", b"a message"), mac(b"a key", b"another message")); ```

We can even create authenticated encryption:

```rust fn aeadencrypt(key: &[u8], nonce: &[u8], ad: &[u8], plaintext: &[u8]) -> Vec { let mut out = vec![0u8; plaintext.len() + lockstitch::TAGLEN]; out[..plaintext.len()].copyfromslice(plaintext);

let mut aead = lockstitch::Protocol::new("com.example.aead"); aead.mix(key); aead.mix(nonce); aead.mix(ad); aead.seal(&mut out);

out }

fn aeaddecrypt(key: &[u8], nonce: &[u8], ad: &[u8], ciphertext: &[u8]) -> Option> { let mut ciphertext = ciphertext.tovec();

let mut aead = lockstitch::Protocol::new("com.example.aead"); aead.mix(key); aead.mix(nonce); aead.mix(ad); aead.open(&mut ciphertext).map(|p| p.to_vec()) }

let plaintext = b"a message".tovec(); let ciphertext = aeadencrypt(b"a key", b"a nonce", b"some data", &plaintext); asserteq!(aeaddecrypt(b"a key", b"a nonce", b"some data", &ciphertext), Some(plaintext)); asserteq!(aeaddecrypt(b"another key", b"a nonce", b"some data", &ciphertext), None); asserteq!(aeaddecrypt(b"a key", b"another nonce", b"some data", &ciphertext), None); asserteq!(aeaddecrypt(b"a key", b"a nonce", b"some other data", &ciphertext), None);

let mut badciphertext = ciphertext.tovec(); badciphertext[5] ^= 1; // flip one bit asserteq!(aeaddecrypt(b"a key", b"a nonce", b"some data", &badciphertext), None); ```

Cargo Features

Performance

Lockstitch's Rocca-S implementation benefits significantly from the use of specific CPU instructions.

x86_64

On x86_64 CPUs, Lockstitch achieves its best performance with the aes and ssse3 CPU features enabled.

To compile a x86_64 binary with support for these features, create a .cargo/config.toml file with the following:

toml [build] rustflags = ["-C", "target-feature=+aes,+ssse3"]

Or use the following RUSTFLAGS environment variable:

sh export RUSTFLAGS="-C target-feature=+aes,+ssse3"

aarch64

Rust's aarch64 code generation includes the ARMv8-A cryptography instructions and NEON vector instructions. No special configuration is required to achieve full performance.

Additional Information

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

License

Copyright © 2023 Coda Hale, Frank Denis

Rocca-S implementation adapted from rust-aegis and zig-rocca.

Distributed under the MIT License.