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 145 146 147 148 149 150 151 152 153 154 155 156
//! Implementation of the double ratchet system/encryption as specified by [Signal][1].
//!
//! **WARNING! This implementation uses P-256 NOT Curve25519 as specified by Signal!**
//!
//! 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)
//! ```
//!
//! # Export / Import Ratchet with encrypted headers
//! This ratchet implements import and export functionality. This works over a bincode backend and
//! maybe useful for saving Ratchets to and loading from a file.
//! ```
//! # use double_ratchet_2::ratchet::RatchetEncHeader;
//! # let sk = [0; 32];
//! # let shared_hka = [1; 32];
//! # let shared_nhkb = [2; 32];
//! let (bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, shared_hka, shared_nhkb);
//! let ex_ratchet = bob_ratchet.export();
//! let im_ratchet = RatchetEncHeader::import(&ex_ratchet);
//! assert_eq!(im_ratchet, bob_ratchet)
//! ```
//!
//! # 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 p256::PublicKey;
mod aead;
mod dh;
mod kdf_root;
mod kdf_chain;
pub mod ratchet;
/// Message Header
pub mod header;