1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! [![Crate](https://img.shields.io/crates/v/double-ratchet-2)](https://crates.io/crates/double-ratchet-2)
//! [![License](https://img.shields.io/github/license/Decentrailzed-Communication-System/double-ratchet-2)](https://github.com/Decentrailzed-Communication-System/double-ratchet-2/blob/main/LICENSE)
//! [![Actions](https://img.shields.io/github/workflow/status/Decentrailzed-Communication-System/double-ratchet-2/Rust)](https://github.com/Decentrailzed-Communication-System/double-ratchet-2/actions)
//!
//! Implementation of the double ratchet system/encryption as specified by [Signal][1].
//!
//! The implementation follows the cryptographic recommendations provided by [Signal][2].
//! The AEAD Algorithm uses a constant Nonce. This might be changed in the future.
//!
//! # Example Usage:
//!
//! ## Standard:
//! ```
//! use double_ratchet_2::ratchet::Ratchet;
//!
//! let sk = [1; 32];                                                 // Initial Key created by a symmetric key agreement protocol
//! let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk);        // Creating Bobs Ratchet (returns Bobs PublicKey)
//! let mut alice_ratchet = Ratchet::init_alice(sk, public_key);      // Creating Alice Ratchet with Bobs PublicKey
//! let data = b"Hello World".to_vec();                               // Data to be encrypted
//! let ad = b"Associated Data";                                      // Associated Data
//!
//! let (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data, ad);   // Encrypting message with Alice Ratchet (Alice always needs to send the first message)
//! let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce, ad); // Decrypt message with Bobs Ratchet
//! assert_eq!(data, decrypted)
//! ```
//!
//! ## With lost message:
//! ```
//! # use double_ratchet_2::ratchet::Ratchet;
//!
//! let sk = [1; 32];                                                 // Initial Key created by a symmetric key agreement protocol
//! let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk);        // Creating Bobs Ratchet (returns Bobs PublicKey)
//! let mut alice_ratchet = Ratchet::init_alice(sk, public_key);      // Creating Alice Ratchet with Bobs PublicKey
//! let data = b"Hello World".to_vec();                               // Data to be encrypted
//! let ad = b"Associated Data";                                      // Associated Data
//!
//! let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data, ad); // Lost message
//! let (header2, encrypted2, nonce2) = alice_ratchet.ratchet_encrypt(&data, ad); // Successful message
//!
//! let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2, ad); // Decrypting second message first
//! let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1, ad); // Decrypting latter message
//!
//! let comp = decrypted1 == data && decrypted2 == data;
//! assert!(comp);
//! ```
//!
//! ## Encryption before recieving inital message
//!
//! ```should_panic
//! use double_ratchet_2::ratchet::Ratchet;
//! let sk = [1; 32];
//! let ad = b"Associated Data";
//! let (mut bob_ratchet, _) = Ratchet::init_bob(sk);
//! let data = b"Hello World".to_vec();
//!
//! let (_, _, _) = bob_ratchet.ratchet_encrypt(&data, ad);
//! ```
//!
//! ## Encryption after recieving initial message
//! However bob can (of course) also encrypt messages. This is possible, after decrypting the first message from alice.
//!
//! ```
//! use double_ratchet_2::ratchet::Ratchet;
//! let sk = [1; 32];
//!
//! let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk);
//! let mut alice_ratchet = Ratchet::init_alice(sk, public_key);
//!
//! let data = b"Hello World".to_vec();
//! let ad = b"Associated Data";
//!
//! let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data, ad);
//! let _decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1, ad);
//!
//! let (header2, encrypted2, nonce2) = bob_ratchet.ratchet_encrypt(&data, ad);
//! let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2, ad);
//!
//! assert_eq!(data, decrypted2);
//! ```
//! ## Constructing and Deconstructing Headers
//!
//! ```
//! # use double_ratchet_2::ratchet::Ratchet;
//! # use double_ratchet_2::header::Header;
//! # let sk = [1; 32];
//! # let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk);
//! # let mut alice_ratchet = Ratchet::init_alice(sk, public_key);
//! # let data = b"hello World".to_vec();
//! # let ad = b"Associated Data";
//! # let (header, _, _) = alice_ratchet.ratchet_encrypt(&data, ad);
//! let header_bytes: Vec<u8> = header.clone().into();
//! let header_const = Header::from(header_bytes);
//! assert_eq!(header, header_const);
//! ```
//!
//! # Example Ratchet with encrypted headers
//!
//! ```
//! use double_ratchet_2::ratchet::RatchetEncHeader;
//! let sk = [0; 32];
//! let shared_hka = [1; 32];
//! let shared_nhkb = [2; 32];
//!
//! let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, shared_hka, shared_nhkb);
//! let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb);
//! let data = b"Hello World".to_vec();
//! let ad = b"Associated Data";
//!
//! let (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data, ad);
//! let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce, ad);
//! assert_eq!(data, decrypted)
//! ```
//!
//! # Features
//!
//! Currently the crate only supports one feature: ring. If feature is enabled the crate switches
//! to ring-compat and uses ring as backend for Sha512 Hashing. May result in slightly better performance.
//!
//!
//! TODO:
//! - [x] Standard Double Ratchet
//! - [x] [Double Ratchet with encrypted headers][3]
//!
//! [1]: https://signal.org/docs/specifications/doubleratchet/
//! [2]: https://signal.org/docs/specifications/doubleratchet/#recommended-cryptographic-algorithms
//! [3]: https://signal.org/docs/specifications/doubleratchet/#double-ratchet-with-header-encryption

#![no_std]
#![allow(stable_features)]

extern crate alloc;

pub use x25519_dalek::PublicKey;

mod aead;
mod dh;
mod kdf_root;
mod kdf_chain;

pub mod ratchet;

/// Message Header
pub mod header;