#signal #double-ratchet #crypto

double-ratchet-2

根据Signal规范实现的Double Ratchet

3个不稳定版本

0.4.0-pre.22022年7月20日
0.3.6 2022年3月23日
0.3.5 2021年10月24日
0.3.3 2021年7月30日

#592 in 加密学

每月35次下载

MIT许可

44KB
753

Crate License Coverage Status Workflow Status Maintenance

double-ratchet-2

根据Signal规范实现的double ratchet系统/加密。

实现遵循Signal提供的加密建议。AEAD算法使用一个常量Nonce。这可能在将来改变。

示例用法

标准

use double_ratchet_2::ratchet::Ratchet;
use x25519_dalek::StaticSecret;

let sk = [1; 32];                                                 // Initial Key created by a symmetric key agreement protocol
let (mut bob_ratchet, public_key) = Ratchet::<StaticSecret>::init_bob(sk);        // Creating Bobs Ratchet (returns Bobs PublicKey)
let mut alice_ratchet = Ratchet::<StaticSecret>::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)

丢失消息

use x25519_dalek::StaticSecret;

let sk = [1; 32];                                                 // Initial Key created by a symmetric key agreement protocol
let (mut bob_ratchet, public_key) = Ratchet::<StaticSecret>::init_bob(sk);        // Creating Bobs Ratchet (returns Bobs PublicKey)
let mut alice_ratchet = Ratchet::<StaticSecret>::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);

在接收到初始消息之前加密

use double_ratchet_2::ratchet::Ratchet;
use x25519_dalek::StaticSecret;
let sk = [1; 32];
let ad = b"Associated Data";
let (mut bob_ratchet, _) = Ratchet::<StaticSecret>::init_bob(sk);
let data = b"Hello World".to_vec();

let (_, _, _) = bob_ratchet.ratchet_encrypt(&data, ad);

在接收到初始消息之后加密

然而,Bob(当然)也可以加密消息。这是在解密Alice的第一条消息之后实现的。

use double_ratchet_2::ratchet::Ratchet;
use x25519_dalek::StaticSecret;
let sk = [1; 32];

let (mut bob_ratchet, public_key) = Ratchet::<StaticSecret>::init_bob(sk);
let mut alice_ratchet = Ratchet::<StaticSecret>::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);

构造和解析头信息

let header_bytes: Vec<u8> = header.concat(b"");
let header_const = Header::<x25519_dalek::PublicKey>::from(header_bytes.as_slice());
assert_eq!(header, header_const);

带有加密头信息的示例Ratchet

use double_ratchet_2::ratchet::RatchetEncHeader;
use x25519_dalek::StaticSecret;
let sk = [0; 32];
let shared_hka = [1; 32];
let shared_nhkb = [2; 32];

let (mut bob_ratchet, public_key) = RatchetEncHeader::<StaticSecret>::init_bob(sk, shared_hka, shared_nhkb);
let mut alice_ratchet = RatchetEncHeader::<StaticSecret>::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)

导出/导入带有加密头信息的Ratchet

此Ratchet实现了导入和导出功能。这通过bincode后端工作,可能对于将Ratchets保存到文件和从文件加载很有用。

use x25519_dalek::StaticSecret;
let (bob_ratchet, public_key) = RatchetEncHeader::<StaticSecret>::init_bob(sk, shared_hka, shared_nhkb);
let ex_ratchet = bob_ratchet.export();
let im_ratchet = RatchetEncHeader::<StaticSecret>::import(&ex_ratchet).unwrap();
assert_eq!(im_ratchet.export(), bob_ratchet.export())

功能

当前crate只支持一个功能:ring。如果启用功能,crate将切换到ring-compat并使用ring作为Sha512哈希的后端。可能会略微提高性能。

待办事项

当前版本:0.4.0-pre.1

许可:MIT

依赖项

~4–5.5MB
~110K SLoC