Added tests and fixed some issues.
I also added documentation.
This commit is contained in:
parent
7bb3e95799
commit
76d7312a9a
6 changed files with 47 additions and 37 deletions
|
@ -9,7 +9,6 @@ keywords = ["double-ratchet", "crypto", "cryptography", "signal"]
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
license-file = "LICENSE"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ use aes_gcm_siv::aead::{NewAead, AeadInPlace};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use rand_core::{OsRng, RngCore};
|
use rand_core::{OsRng, RngCore};
|
||||||
|
|
||||||
const CONSTANT_NONCE: &[u8] = b"Super Noncel";
|
|
||||||
|
|
||||||
pub fn encrypt(mk: &[u8; 32], plaintext: &[u8], associated_data: &[u8]) -> (Vec<u8>, [u8; 12]) {
|
pub fn encrypt(mk: &[u8; 32], plaintext: &[u8], associated_data: &[u8]) -> (Vec<u8>, [u8; 12]) {
|
||||||
let key = Key::from_slice(mk);
|
let key = Key::from_slice(mk);
|
||||||
let cipher = Aes256GcmSiv::new(key);
|
let cipher = Aes256GcmSiv::new(key);
|
||||||
|
|
|
@ -4,7 +4,7 @@ use alloc::vec::Vec;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::aead::encrypt;
|
use crate::aead::encrypt;
|
||||||
use aes_gcm_siv::{Key, Nonce, Aes256GcmSiv};
|
use aes_gcm_siv::{Key, Nonce, Aes256GcmSiv};
|
||||||
use aes_gcm_siv::aead::{NewAead, AeadInPlace, Error};
|
use aes_gcm_siv::aead::{NewAead, AeadInPlace};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::dh::gen_key_pair;
|
use crate::dh::gen_key_pair;
|
||||||
|
@ -93,9 +93,9 @@ impl From<&[u8]> for Header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<Vec<u8>> for Header {
|
impl From<Header> for Vec<u8> {
|
||||||
fn into(self) -> Vec<u8> {
|
fn from(s: Header) -> Self {
|
||||||
self.concat()
|
s.concat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -89,6 +89,23 @@
|
||||||
//! assert_eq!(header, header_const);
|
//! 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 (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data);
|
||||||
|
//! let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce);
|
||||||
|
//! assert_eq!(data, decrypted)
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
//! # Features
|
//! # Features
|
||||||
//!
|
//!
|
||||||
//! Currently the crate only supports one feature: ring. If feature is enabled the crate switches
|
//! Currently the crate only supports one feature: ring. If feature is enabled the crate switches
|
||||||
|
|
|
@ -12,6 +12,8 @@ use crate::aead::{encrypt, decrypt};
|
||||||
|
|
||||||
const MAX_SKIP: usize = 100;
|
const MAX_SKIP: usize = 100;
|
||||||
|
|
||||||
|
type HeaderNonceCipherNonce = ((Vec<u8>, [u8; 12]), Vec<u8>, [u8; 12]);
|
||||||
|
|
||||||
/// Object Representing Ratchet
|
/// Object Representing Ratchet
|
||||||
pub struct Ratchet {
|
pub struct Ratchet {
|
||||||
dhs: DhKeyPair,
|
dhs: DhKeyPair,
|
||||||
|
@ -200,7 +202,7 @@ impl RatchetEncHeader {
|
||||||
(ratchet, public_key)
|
(ratchet, public_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ratchet_encrypt(&mut self, plaintext: &[u8]) -> ((Vec<u8>, [u8; 12]), Vec<u8>, [u8; 12]) {
|
pub fn ratchet_encrypt(&mut self, plaintext: &[u8]) -> HeaderNonceCipherNonce {
|
||||||
let (cks, mk) = kdf_ck(&self.cks.unwrap());
|
let (cks, mk) = kdf_ck(&self.cks.unwrap());
|
||||||
self.cks = Some(cks);
|
self.cks = Some(cks);
|
||||||
let header = Header::new(&self.dhs, self.pn, self.ns);
|
let header = Header::new(&self.dhs, self.pn, self.ns);
|
||||||
|
@ -212,28 +214,28 @@ impl RatchetEncHeader {
|
||||||
|
|
||||||
fn try_skipped_message_keys(&mut self, enc_header: &(Vec<u8>, [u8; 12]),
|
fn try_skipped_message_keys(&mut self, enc_header: &(Vec<u8>, [u8; 12]),
|
||||||
ciphertext: &[u8], nonce: &[u8; 12]) -> Option<Vec<u8>> {
|
ciphertext: &[u8], nonce: &[u8; 12]) -> Option<Vec<u8>> {
|
||||||
for ((hk, n), mk) in self.mkskipped.iter() {
|
|
||||||
let header = Header::decrypt(hk, &enc_header.0, &enc_header.1);
|
let ret_data = self.mkskipped.clone().into_iter().find(|e| {
|
||||||
|
let header = Header::decrypt(&e.0.0, &enc_header.0, &enc_header.1);
|
||||||
match header {
|
match header {
|
||||||
None => { continue },
|
None => false,
|
||||||
Some(h) => {
|
Some(h) => h.n == e.0.1
|
||||||
if h.n == *n {
|
}
|
||||||
let mk = mk.clone();
|
});
|
||||||
self.mkskipped.remove(&(*hk, *n));
|
match ret_data {
|
||||||
return Some(decrypt(&mk, ciphertext, &h.concat(), nonce))
|
None => { None },
|
||||||
|
Some(data) => {
|
||||||
|
let header = Header::decrypt(&data.0.0, &enc_header.0, &enc_header.1);
|
||||||
|
let mk = data.1;
|
||||||
|
self.mkskipped.remove(&(data.0.0, data.0.1));
|
||||||
|
Some(decrypt(&mk, ciphertext, &header.unwrap().concat(), nonce))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt_header(&mut self, enc_header: &(Vec<u8>, [u8; 12])) -> Result<(Header, bool), &str> {
|
fn decrypt_header(&mut self, enc_header: &(Vec<u8>, [u8; 12])) -> Result<(Header, bool), &str> {
|
||||||
let header = Header::decrypt(&self.hkr, &enc_header.0, &enc_header.1);
|
let header = Header::decrypt(&self.hkr, &enc_header.0, &enc_header.1);
|
||||||
match header {
|
if let Some(h) = header { return Ok((h, false)) };
|
||||||
Some(h) => { return Ok((h, false)) },
|
|
||||||
None => {},
|
|
||||||
}
|
|
||||||
let header = Header::decrypt(&self.nhkr, &enc_header.0, &enc_header.1);
|
let header = Header::decrypt(&self.nhkr, &enc_header.0, &enc_header.1);
|
||||||
match header {
|
match header {
|
||||||
Some(h) => Ok((h, true)),
|
Some(h) => Ok((h, true)),
|
||||||
|
@ -245,8 +247,7 @@ impl RatchetEncHeader {
|
||||||
if self.nr + MAX_SKIP < until {
|
if self.nr + MAX_SKIP < until {
|
||||||
return Err("Skipping went wrong")
|
return Err("Skipping went wrong")
|
||||||
}
|
}
|
||||||
match self.ckr {
|
if let Some(d) = self.ckr {
|
||||||
Some(d) => {
|
|
||||||
while self.nr < until {
|
while self.nr < until {
|
||||||
let (ckr, mk) = kdf_ck(&d);
|
let (ckr, mk) = kdf_ck(&d);
|
||||||
self.ckr = Some(ckr);
|
self.ckr = Some(ckr);
|
||||||
|
@ -254,8 +255,6 @@ impl RatchetEncHeader {
|
||||||
self.nr += 1
|
self.nr += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,10 +280,7 @@ impl RatchetEncHeader {
|
||||||
|
|
||||||
pub fn ratchet_decrypt(&mut self, enc_header: &(Vec<u8>, [u8; 12]), ciphertext: &[u8], nonce: &[u8; 12]) -> Vec<u8> {
|
pub fn ratchet_decrypt(&mut self, enc_header: &(Vec<u8>, [u8; 12]), ciphertext: &[u8], nonce: &[u8; 12]) -> Vec<u8> {
|
||||||
let plaintext = self.try_skipped_message_keys(enc_header, ciphertext, nonce);
|
let plaintext = self.try_skipped_message_keys(enc_header, ciphertext, nonce);
|
||||||
match plaintext {
|
if let Some(d) = plaintext { return d };
|
||||||
Some(d) => { return d },
|
|
||||||
None => {}
|
|
||||||
};
|
|
||||||
let (header, dh_ratchet) = self.decrypt_header(enc_header).unwrap();
|
let (header, dh_ratchet) = self.decrypt_header(enc_header).unwrap();
|
||||||
if dh_ratchet {
|
if dh_ratchet {
|
||||||
self.skip_message_keys(header.pn).unwrap();
|
self.skip_message_keys(header.pn).unwrap();
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn ratchet_ench_panic_bob() {
|
||||||
let sk = [1; 32];
|
let sk = [1; 32];
|
||||||
let shared_hka = [2; 32];
|
let shared_hka = [2; 32];
|
||||||
let shared_nhkb = [3; 32];
|
let shared_nhkb = [3; 32];
|
||||||
let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk,
|
let (mut bob_ratchet, _) = RatchetEncHeader::init_bob(sk,
|
||||||
shared_hka,
|
shared_hka,
|
||||||
shared_nhkb);
|
shared_nhkb);
|
||||||
let data = include_bytes!("../src/header.rs").to_vec();
|
let data = include_bytes!("../src/header.rs").to_vec();
|
||||||
|
|
Loading…
Reference in a new issue