A pure Rust implementation of the Double Ratchet algorithm as described by Signal.
This implementation follows the cryptographic recommendations provided by Signal. The AEAD algorithm uses a constant Nonce. This might be changed in the future.
Fork of double-ratchet-2.
Alice encrypts a message which is then decrypted by Bob.
```rust use doubleratchetrs::Ratchet;
let sk = [1; 32]; // Shared key created by a symmetric key agreement protocol
let (mut bobratchet, publickey) = Ratchet::initbob(sk); // Creating Bob's Ratchet (returns Bob's PublicKey) let mut aliceratchet = Ratchet::initalice(sk, publickey); // Creating Alice's Ratchet with Bob's PublicKey
let data = b"Hello World".to_vec(); // Data to be encrypted let ad = b"Associated Data"; // Associated data
let (header, encrypted, nonce) = aliceratchet.encrypt(&data, ad); // Encrypting message with Alice's Ratchet (Alice always needs to send the first message) let decrypted = bobratchet.decrypt(&header, &encrypted, &nonce, ad); // Decrypt message with Bob's Ratchet
assert_eq!(data, decrypted) ```
Alice encrypts 2 messages for Bob. The latest message must be decrypted first.
```rust use doubleratchetrs::Ratchet;
let sk = [1; 32]; // Shared key created by a symmetric key agreement protocol
let (mut bobratchet, publickey) = Ratchet::initbob(sk); // Creating Bob's Ratchet (returns Bob's PublicKey) let mut aliceratchet = Ratchet::initalice(sk, publickey); // Creating Alice's Ratchet with Bob's PublicKey
let data = b"Hello World".to_vec(); // Data to be encrypted let ad = b"Associated Data"; // Associated data
let (header1, encrypted1, nonce1) = aliceratchet.encrypt(&data, ad); // Lost message let (header2, encrypted2, nonce2) = aliceratchet.encrypt(&data, ad); // Successful message
let decrypted2 = bobratchet.decrypt(&header2, &encrypted2, &nonce2, ad); // Decrypting second message first let decrypted1 = bobratchet.decrypt(&header1, &encrypted1, &nonce1, ad); // Decrypting latter message
asserteq!(data, decrypted1); asserteq!(data, decrypted2); ```
Bob encrypts a message before decrypting one from Alice. This will result in a panic.
```rust use doubleratchetrs::Ratchet;
let sk = [1; 32];
let (mut bobratchet, _) = Ratchet::initbob(sk);
let data = b"Hello World".to_vec(); let ad = b"Associated Data";
let (, _, _) = bobratchet.encrypt(&data, ad); ```
Bob can also encrypt messages. This is only possible after decrypting one from Alice first though.
```rust use doubleratchetrs::Ratchet;
let sk = [1; 32];
let (mut bobratchet, publickey) = Ratchet::initbob(sk); let mut aliceratchet = Ratchet::initalice(sk, publickey);
let data = b"Hello World".to_vec(); let ad = b"Associated Data";
let (header1, encrypted1, nonce1) = aliceratchet.encrypt(&data, ad); let _decrypted1 = bobratchet.decrypt(&header1, &encrypted1, &nonce1, ad);
let (header2, encrypted2, nonce2) = bobratchet.encrypt(&data, ad); let decrypted2 = aliceratchet.decrypt(&header2, &encrypted2, &nonce2, ad);
assert_eq!(data, decrypted2); ```
```rust use doubleratchetrs::{Header, Ratchet};
let sk = [1; 32];
let (mut bobratchet, publickey) = Ratchet::initbob(sk); let mut aliceratchet = Ratchet::initalice(sk, publickey);
let data = b"hello World".to_vec(); let ad = b"Associated Data";
let (header, , _) = aliceratchet.encrypt(&data, ad);
let headerbytes: Vec
asserteq!(header, headerconst); ```
```rust use doubleratchetrs::RatchetEncHeader;
let sk = [0; 32]; let sharedhka = [1; 32]; let sharednhkb = [2; 32];
let (mut bobratchet, publickey) = RatchetEncHeader::initbob(sk, sharedhka, sharednhkb); let mut aliceratchet = RatchetEncHeader::initalice(sk, publickey, sharedhka, sharednhkb);
let data = b"Hello World".to_vec(); let ad = b"Associated Data";
let (header, encrypted, nonce) = aliceratchet.encrypt(&data, ad); let decrypted = bobratchet.decrypt(&header, &encrypted, &nonce, ad);
assert_eq!(data, decrypted) ```
This can be used for storing and using ratchets in a file.
```rust use doubleratchetrs::RatchetEncHeader;
let sk = [0; 32]; let sharedhka = [1; 32]; let sharednhkb = [2; 32];
let (bobratchet, publickey) = RatchetEncHeader::initbob(sk, sharedhka, sharednhkb); let exratchet = bobratchet.export(); let imratchet = RatchetEncHeader::import(&ex_ratchet).unwrap();
asserteq!(imratchet, bob_ratchet) ```
hashbrown: Use hashbrown for HashMap. Enabled by default for no_std support.std: Use std instead of alloc. Can be used with hashbrown, but it isn't required.The current MSRV is 1.60.0 without hashbrown and 1.64.0 with hashbrown.
This project is licensed under the MIT license.