ck_meow/lib.rs
1//! This crate is an implementation of [STROBE](https://strobe.sourceforge.io/specs/) using KitTen (reduced round [Keccak](https://keccak.team/keccak.html)).
2//! STROBE is a framework for symmetric cryptography protocols, similar to
3//! how Noise works for key exchange.
4//!
5//! Because this project combines a Noise-like framework with KitTen, I called
6//! it **Meow**.
7//!
8//! # Rationale
9//!
10//! STROBE uses the 24 round variant of Keccak.
11//! Having been [too much crypto-pilled](https://eprint.iacr.org/2019/1492),
12//! I think 24 rounds is excessive, and instead think that the 10 rounds
13//! of KitTen are sufficient.
14//!
15//! Following in the TMC rationale, I also hardcode 128 bits of security
16//! into the protocol.
17//!
18//! There are also some slight changes to the protocol, such as not allowing
19//! MACs to be created or verified in a streaming fashion, or setting
20//! a default length for ratcheting.
21//! These don't change the behavior of the other operations though, internally,
22//! these work like STROBE, just with a different permutation.
23//!
24//! # Use Cases
25//!
26//! The use cases are that of STROBE essentially.
27//! You can use the framework for encryption, hashing, etc.
28//!
29//! ## Encryption
30//!
31//! For basic encryption, the flow is that each party sets up their Meow state,
32//! seeds it with a key, and then either sends or receives a message.
33//!
34//! ```rust
35//! use ck_meow::Meow;
36//!
37//! let key = [0xFF; 32];
38//!
39//! let message = b"hello world!";
40//!
41//! let mut encrypted = message.to_owned();
42//! let mut meow0 = Meow::new(b"my protocol");
43//! meow0.key(&key, false);
44//! meow0.send_enc(&mut encrypted, false);
45//!
46//! let mut plaintext = encrypted.clone();
47//! let mut meow1 = Meow::new(b"my protocol");
48//! meow1.key(&key, false);
49//! meow1.recv_enc(&mut plaintext, false);
50//!
51//! assert_eq!(&plaintext, message);
52//! ```
53//!
54//! ### Randomized Encryption
55//!
56//! It's also very easy to add a nonce to the encryption scheme:
57//!
58//! ```rust
59//! use ck_meow::Meow;
60//!
61//! let key = [0xFF; 32];
62//! let nonce = [0xAA; 32];
63//!
64//! let message = b"hello world!";
65//!
66//! let mut encrypted = message.to_owned();
67//! let mut meow0 = Meow::new(b"my protocol");
68//! meow0.key(&key, false);
69//! meow0.send_clr(&nonce, false);
70//! meow0.send_enc(&mut encrypted, false);
71//!
72//! let mut plaintext = encrypted.clone();
73//! let mut meow1 = Meow::new(b"my protocol");
74//! meow1.key(&key, false);
75//! meow1.recv_clr(&nonce, false);
76//! meow1.recv_enc(&mut plaintext, false);
77//!
78//! assert_eq!(&plaintext, message);
79//! ```
80//!
81//! All that was need was to add in calls to `send_clr` and `recv_clr`.
82//! In the real protocol, this nonce would be sent to the other participant.
83//!
84//! ### AEAD
85//!
86//! From there, it's straightforward to turn this into a full fledged AEAD scheme.
87//! We can also incorporate additional data into the state, and we can also generate
88//! and check MACs.
89
90//! ```rust
91//! use ck_meow::Meow;
92//!
93//! let key = [0xFF; 32];
94//! let nonce = [0xAA; 32];
95//!
96//! let message = b"hello world!";
97//!
98//! let mut encrypted = message.to_owned();
99//! let mut meow0 = Meow::new(b"my protocol");
100//! meow0.key(&key, false);
101//! meow0.send_clr(&nonce, false);
102//! meow0.ad(b"hello again!", false);
103//! meow0.send_enc(&mut encrypted, false);
104//! let mut mac = [0u8; 32];
105//! meow0.send_mac(&mut mac);
106//!
107//!
108//! let mut plaintext = encrypted.clone();
109//! let mut meow1 = Meow::new(b"my protocol");
110//! meow1.key(&key, false);
111//! meow1.recv_clr(&nonce, false);
112//! meow1.ad(b"hello again!", false);
113//! meow1.recv_enc(&mut plaintext, false);
114//! assert!(meow1.recv_mac(&mut mac).is_ok());
115//!
116//! assert_eq!(&plaintext, message);
117//! ```
118//!
119//! The essential new functionality here is `send_mac / recv_mac`, which allows
120//! creating and verifying a MAC which attests to the integrity of the entire
121//! transcript thus far.
122//!
123//! ## Hashing
124//!
125//! It's also possible to use Meow as a very simple hash function:
126//!
127//! ```rust
128//! use ck_meow::Meow;
129//!
130//! let mut meow = Meow::new(b"my hash function");
131//! meow.ad(b"big data", false);
132//! // Same as hashing to entire string at once.
133//! meow.ad(b"big ", false);
134//! meow.ad(b"data", true);
135//! let mut hash = [0u8; 32];
136//! meow.prf(&mut hash, false);
137//! ```
138//!
139//! You absorb in data with `ad`, and then squeeze it out using the `prf` function.
140//! This example also illustrates using `more`, which allows us to split up
141//! operations into multiple calls. The second call to the hash function
142//! is equivalent.
143//!
144//! ## Fiat-Shamirization
145//!
146//! Not only can Meow be used for hashing in one stroke, it's also possible
147//! to alternate between absorbing and squeezing out data, which is useful
148//! for making interactive public coin protocols non-interactive:
149//!
150//! ```rust
151//! use ck_meow::Meow;
152//!
153//! let mut meow = Meow::new(b"my protocol");
154//! meow.ad(b"some data", false);
155//! meow.ad(b"some more data", false);
156//! let mut challenge = [0u8; 32];
157//! meow.prf(&mut challenge, false);
158//! meow.ad(b"even more data", false);
159//! let mut another_challenge = [0u8; 32];
160//! meow.prf(&mut another_challenge, false);
161//! ```
162//!
163//! (Note that it would be a good ad to add some `meta_ad` calls for framing,
164//! defining the length of the inputs).
165#![cfg_attr(not(test), no_std)]
166mod kitten;
167mod meow;
168// For much heavier tests.
169#[cfg(test)]
170mod test;
171
172pub use crate::meow::{MacError, Meow};