Double ratchet FFI usage in Nim (#14)

* feat: ffi

* feat: ffi interface and header generation

* feat: nim ffi example

* chore: doc

* fix: encrypt state clean

* chore: zeroize when drop
This commit is contained in:
kaichao 2026-01-21 17:24:20 +08:00 committed by GitHub
parent fc76453f4c
commit 58392841cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 720 additions and 7 deletions

3
.gitignore vendored
View File

@ -21,3 +21,6 @@ target
#.idea/
*/.DS_Store
# Compiled binary
**/ffi_nim_example

295
Cargo.lock generated
View File

@ -114,7 +114,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]
[[package]]
@ -137,10 +137,53 @@ dependencies = [
"hkdf",
"rand",
"rand_core",
"safer-ffi",
"thiserror",
"x25519-dalek",
"zeroize",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "ext-trait"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5"
dependencies = [
"ext-trait-proc_macros",
]
[[package]]
name = "ext-trait-proc_macros"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "extension-traits"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537"
dependencies = [
"ext-trait",
]
[[package]]
name = "extern-c"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320bea982e85d42441eb25c49b41218e7eaa2657e8f90bc4eca7437376751e23"
[[package]]
name = "fiat-crypto"
version = "0.2.9"
@ -168,6 +211,12 @@ dependencies = [
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "hkdf"
version = "0.12.4"
@ -186,6 +235,16 @@ dependencies = [
"digest",
]
[[package]]
name = "indexmap"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.4"
@ -195,6 +254,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "inventory"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
dependencies = [
"rustversion",
]
[[package]]
name = "libc"
version = "0.2.178"
@ -208,12 +276,40 @@ dependencies = [
"thiserror",
]
[[package]]
name = "macro_rules_attribute"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862"
dependencies = [
"macro_rules_attribute-proc_macro",
"paste",
]
[[package]]
name = "macro_rules_attribute-proc_macro"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d"
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "poly1305"
version = "0.8.0"
@ -234,6 +330,25 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "prettyplease"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
dependencies = [
"proc-macro2",
"syn 1.0.109",
]
[[package]]
name = "proc-macro-crate"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.103"
@ -291,6 +406,50 @@ dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "safer-ffi"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435fdd58b61a6f1d8545274c1dfa458e905ff68c166e65e294a0130ef5e675bd"
dependencies = [
"extern-c",
"inventory",
"libc",
"macro_rules_attribute",
"paste",
"safer_ffi-proc_macros",
"scopeguard",
"stabby",
"uninit",
"unwind_safe",
"with_builtin_macros",
]
[[package]]
name = "safer_ffi-proc_macros"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f25be5ba5f319542edb31925517e0380245ae37df50a9752cdbc05ef948156"
dependencies = [
"macro_rules_attribute",
"prettyplease",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.27"
@ -324,7 +483,48 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]
[[package]]
name = "sha2-const-stable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9"
[[package]]
name = "stabby"
version = "36.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b7e94eaf470c2e76b5f15fb2fb49714471a36cc512df5ee231e62e82ec79f8"
dependencies = [
"rustversion",
"stabby-abi",
]
[[package]]
name = "stabby-abi"
version = "36.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dc7a63b8276b54e51bfffe3d85da56e7906b2dcfcb29018a8ab666c06734c1a"
dependencies = [
"rustc_version",
"rustversion",
"sha2-const-stable",
"stabby-macros",
]
[[package]]
name = "stabby-macros"
version = "36.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eecb7ec5611ec93ec79d120fbe55f31bea234dc1bed1001d4a071bb688651615"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"rand",
"syn 1.0.109",
]
[[package]]
@ -333,6 +533,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.111"
@ -361,7 +572,37 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]
[[package]]
name = "toml_datetime"
version = "0.7.5+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.23.10+spec-1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
dependencies = [
"indexmap",
"toml_datetime",
"toml_parser",
"winnow",
]
[[package]]
name = "toml_parser"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
dependencies = [
"winnow",
]
[[package]]
@ -376,6 +617,15 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "uninit"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e130f2ed46ca5d8ec13c7ff95836827f92f5f5f37fd2b2bf16f33c408d98bb6"
dependencies = [
"extension-traits",
]
[[package]]
name = "universal-hash"
version = "0.5.1"
@ -386,6 +636,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "unwind_safe"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3"
[[package]]
name = "version_check"
version = "0.9.5"
@ -398,6 +654,35 @@ version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "winnow"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
dependencies = [
"memchr",
]
[[package]]
name = "with_builtin_macros"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a59d55032495429b87f9d69954c6c8602e4d3f3e0a747a12dea6b0b23de685da"
dependencies = [
"with_builtin_macros-proc_macros",
]
[[package]]
name = "with_builtin_macros-proc_macros"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15bd7679c15e22924f53aee34d4e448c45b674feb6129689af88593e129f8f42"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "x25519-dalek"
version = "2.0.1"
@ -427,7 +712,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]
[[package]]
@ -447,5 +732,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]

View File

@ -3,6 +3,13 @@ name = "double-ratchets"
version = "0.0.1"
edition = "2024"
[lib]
crate-type = ["rlib", "cdylib"]
[[bin]]
name = "generate-headers"
required-features = ["headers"]
[dependencies]
x25519-dalek = { version="2.0.1", features=["static_secrets"] }
chacha20poly1305 = "0.10.1"
@ -11,3 +18,8 @@ rand = "0.8.5"
hkdf = "0.12.4"
thiserror = "2"
blake2 = "0.10.6"
safer-ffi = "0.1.13"
zeroize = "1.8.2"
[features]
headers = ["safer-ffi/headers"]

View File

@ -20,3 +20,12 @@ Run examples,
```
cargo run --example double_ratchet_basic
```
Run Nim FFI example,
```bash
# In the root folder (libchat)
cargo build --release
# In ffi-nim-example folder
nimble run
```

View File

@ -0,0 +1,13 @@
# Package
version = "0.1.0"
author = "kaichaosun"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
bin = @["ffi_nim_example"]
# Dependencies
requires "nim >= 2.2.4"

View File

@ -0,0 +1,144 @@
when defined(macosx):
{.passL: "-Wl,-rpath,@executable_path/../../target/release".}
when defined(linux):
{.passL: "-Wl,-rpath,'$ORIGIN/../../target/release'".}
# Portable dynlib name with override capability (-d:RLN_LIB:"...")
when defined(macosx):
const DR_LIB* {.strdefine.} = "libdouble_ratchets.dylib"
elif defined(linux):
const DR_LIB* {.strdefine.} = "libdouble_ratchets.so"
elif defined(windows):
const DR_LIB* {.strdefine.} = "double_ratchets.dll"
else:
const DR_LIB* {.strdefine.} = "double_ratchets"
type FFIRatchetState* = object
type FFIEncryptResult* = object
type FFIInstallationKeyPair* = object
type CSize* = csize_t
type Vec_uint8* = object
dataPtr*: ptr uint8
len*: CSize
cap*: CSize
type Array_uint8_32* {.bycopy.} = object
idx*: array[32, uint8]
type CResult_Vec_uint8_Vec_uint8* {.bycopy.} = object ## <No documentation available>
ok*: Vec_uint8
err*: Vec_uint8
proc double_ratchet_init_receiver*(
shared_secret: Array_uint8_32, keypair: ptr FFIInstallationKeyPair
): ptr FFIRatchetState {.importc, dynlib: DR_LIB.}
proc double_ratchet_init_sender*(
shared_secret: Array_uint8_32, remote_pub: Array_uint8_32
): ptr FFIRatchetState {.importc, dynlib: DR_LIB.}
proc double_ratchet_encrypt_message*(
state: ptr FFIRatchetState, plaintext: ptr Vec_uint8
): ptr FFIEncryptResult {.importc, dynlib: DR_LIB.}
proc double_ratchet_descrypt_message*(
state: ptr FFIRatchetState, encrypted: ptr FFIEncryptResult
): CResult_Vec_uint8_Vec_uint8 {.importc, dynlib: DR_LIB.}
proc ratchet_state_destroy*(state: ptr FFIRatchetState) {.importc, dynlib: DR_LIB.}
proc encrypt_result_destroy*(result: ptr FFIEncryptResult) {.importc, dynlib: DR_LIB.}
proc installation_key_pair_generate*(): ptr FFIInstallationKeyPair {.
importc, dynlib: DR_LIB
.}
proc installation_key_pair_public*(
keypair: ptr FFIInstallationKeyPair
): Array_uint8_32 {.importc, dynlib: DR_LIB.}
proc installation_key_pair_destroy*(
keypair: ptr FFIInstallationKeyPair
) {.importc, dynlib: DR_LIB.}
proc ffi_c_string_free*(s: Vec_uint8) {.importc, cdecl, dynlib: DR_LIB.}
proc asString*(v: Vec_uint8): string =
if v.dataPtr.isNil or v.len == 0:
return ""
result = newString(v.len.int)
copyMem(addr result[0], v.dataPtr, v.len.int)
when isMainModule:
echo("start run")
# === Shared secret (like X3DH) ===
var sharedSecret: Array_uint8_32
for i in 0 .. 31:
sharedSecret.idx[i] = 42'u8
# === Bob generates DH keypair ===
let bobKey = installation_key_pair_generate()
let bobPub = installation_key_pair_public(bobKey)
echo("bob public key:", bobPub)
# === Alice initializes as sender ===
let alice = double_ratchet_init_sender(sharedSecret, bobPub)
# # === Bob initializes as receiver ===
let bob = double_ratchet_init_receiver(sharedSecret, bobKey)
# # === Alice sends message to Bob ===
var msg1: array[3, uint8] = [11'u8, 12, 13]
var msg1Vec = Vec_uint8(
dataPtr: cast[ptr uint8](addr msg1[0]), len: CSize(msg1.len), cap: CSize(msg1.len)
)
let enc1 = double_ratchet_encrypt_message(alice, addr msg1Vec)
let dec1 = double_ratchet_descrypt_message(bob, enc1)
encrypt_result_destroy(enc1)
if dec1.err.dataPtr != nil:
echo "Bob failed to decrypt: ", asString(dec1.err)
ffi_c_string_free(dec1.err)
ratchet_state_destroy(alice)
ratchet_state_destroy(bob)
installation_key_pair_destroy(bobKey)
quit 1
let res1 = dec1.ok
var plaintext1: array[3, uint8]
copyMem(addr plaintext1[0], res1.dataPtr, res1.len.int)
echo "Bob received: ", plaintext1
# # === Bob replies (triggers DH ratchet) ===
var msg2: array[3, uint8] = [1'u8, 2, 3]
var msg2Vec = Vec_uint8(
dataPtr: cast[ptr uint8](addr msg2[0]), len: CSize(msg1.len), cap: CSize(msg1.len)
)
let enc2 = double_ratchet_encrypt_message(bob, addr msg2Vec)
let dec2 = double_ratchet_descrypt_message(alice, enc2)
encrypt_result_destroy(enc2)
if dec2.err.dataPtr != nil:
echo "Alice failed to decrypt: ", asString(dec2.err)
ffi_c_string_free(dec2.err)
ratchet_state_destroy(alice)
ratchet_state_destroy(bob)
installation_key_pair_destroy(bobKey)
quit 1
let res2 = dec2.ok
var plaintext2: array[3, uint8]
copyMem(addr plaintext2[0], res2.dataPtr, res2.len.int)
echo "Alice received: ", plaintext2
# # === Cleanup ===
ratchet_state_destroy(alice)
ratchet_state_destroy(bob)
installation_key_pair_destroy(bobKey)
echo("==end==\n")

View File

@ -0,0 +1,5 @@
use double_ratchets::ffi;
fn main() -> std::io::Result<()> {
ffi::generate_headers()
}

View File

@ -0,0 +1,81 @@
use safer_ffi::prelude::*;
use x25519_dalek::PublicKey;
use crate::{
Header, RatchetState,
ffi::{key::FFIInstallationKeyPair, utils::CResult},
};
#[derive_ReprC]
#[repr(opaque)]
pub struct FFIRatchetState(pub(crate) RatchetState);
#[derive_ReprC]
#[repr(opaque)]
pub struct FFIEncryptResult {
pub ciphertext: Vec<u8>,
pub header: Header,
}
#[ffi_export]
fn double_ratchet_init_sender(
shared_secret: [u8; 32],
remote_pub: [u8; 32],
) -> repr_c::Box<FFIRatchetState> {
let state = RatchetState::init_sender(shared_secret, PublicKey::from(remote_pub));
Box::new(FFIRatchetState(state)).into()
}
#[ffi_export]
fn double_ratchet_init_receiver(
shared_secret: [u8; 32],
keypair: &FFIInstallationKeyPair,
) -> repr_c::Box<FFIRatchetState> {
let state = RatchetState::init_receiver(shared_secret, keypair.0.clone());
Box::new(FFIRatchetState(state)).into()
}
#[ffi_export]
fn double_ratchet_encrypt_message(
state: &mut FFIRatchetState,
plaintext: &repr_c::Vec<u8>,
) -> repr_c::Box<FFIEncryptResult> {
let encrypted = state.0.encrypt_message(plaintext);
let result = FFIEncryptResult {
ciphertext: encrypted.0,
header: encrypted.1,
};
Box::new(result).into()
}
//TODO rename decrypt
#[ffi_export]
fn double_ratchet_descrypt_message(
state: &mut FFIRatchetState,
encrypted: &FFIEncryptResult,
) -> CResult<repr_c::Vec<u8>, repr_c::String> {
let decrypted = state
.0
.decrypt_message(&encrypted.ciphertext, encrypted.header.clone());
match decrypted {
Ok(plaintext) => CResult {
ok: Some(plaintext.into()),
err: None,
},
Err(err) => CResult {
ok: None,
err: Some(err.to_string().into()),
},
}
}
#[ffi_export]
fn ratchet_state_destroy(state: repr_c::Box<FFIRatchetState>) {
drop(state)
}
#[ffi_export]
fn encrypt_result_destroy(result: repr_c::Box<FFIEncryptResult>) {
drop(result)
}

View File

@ -0,0 +1,22 @@
use safer_ffi::prelude::*;
use crate::InstallationKeyPair;
#[derive_ReprC]
#[repr(opaque)]
pub struct FFIInstallationKeyPair(pub(crate) InstallationKeyPair);
#[ffi_export]
fn installation_key_pair_generate() -> repr_c::Box<FFIInstallationKeyPair> {
Box::new(FFIInstallationKeyPair(InstallationKeyPair::generate())).into()
}
#[ffi_export]
fn installation_key_pair_public(keypair: &FFIInstallationKeyPair) -> [u8; 32] {
keypair.0.public().clone().to_bytes()
}
#[ffi_export]
fn installation_key_pair_destroy(keypair: repr_c::Box<FFIInstallationKeyPair>) {
drop(keypair)
}

View File

@ -0,0 +1,10 @@
pub mod doubleratchet;
pub mod key;
pub mod utils;
#[cfg(feature = "headers")]
pub fn generate_headers() -> std::io::Result<()> {
safer_ffi::headers::builder()
.to_file("double_ratchet.h")?
.generate()
}

View File

@ -0,0 +1,13 @@
use safer_ffi::prelude::*;
#[derive_ReprC]
#[repr(C)]
pub struct CResult<T: ReprC, Err: ReprC> {
pub ok: Option<T>,
pub err: Option<Err>,
}
#[ffi_export]
pub fn ffi_c_string_free(s: repr_c::String) {
drop(s);
}

View File

@ -1,9 +1,10 @@
use rand_core::OsRng;
use x25519_dalek::{PublicKey, StaticSecret};
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::types::SharedSecret;
#[derive(Clone)]
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct InstallationKeyPair {
secret: StaticSecret,
public: PublicKey,

View File

@ -1,5 +1,6 @@
pub mod aead;
pub mod errors;
pub mod ffi;
pub mod hkdf;
pub mod keypair;
pub mod state;

View File

@ -35,7 +35,7 @@ pub struct RatchetState<D: HkdfInfo = DefaultDomain> {
}
/// Public header attached to every encrypted message (unencrypted but authenticated).
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Header {
pub dh_pub: PublicKey,
pub msg_num: u32,

114
double_ratchet.h Normal file
View File

@ -0,0 +1,114 @@
/*! \file */
/*******************************************
* *
* File auto-generated by `::safer_ffi`. *
* *
* Do not manually edit this file. *
* *
*******************************************/
#ifndef __RUST_DOUBLE_RATCHETS__
#define __RUST_DOUBLE_RATCHETS__
#ifdef __cplusplus
extern "C" {
#endif
/** <No documentation available> */
typedef struct FFIRatchetState FFIRatchetState_t;
/** <No documentation available> */
typedef struct FFIEncryptResult FFIEncryptResult_t;
#include <stddef.h>
#include <stdint.h>
/** \brief
* Same as [`Vec<T>`][`rust::Vec`], but with guaranteed `#[repr(C)]` layout
*/
typedef struct Vec_uint8 {
/** <No documentation available> */
uint8_t * ptr;
/** <No documentation available> */
size_t len;
/** <No documentation available> */
size_t cap;
} Vec_uint8_t;
/** <No documentation available> */
typedef struct CResult_Vec_uint8_Vec_uint8 {
/** <No documentation available> */
Vec_uint8_t ok;
/** <No documentation available> */
Vec_uint8_t err;
} CResult_Vec_uint8_Vec_uint8_t;
/** <No documentation available> */
CResult_Vec_uint8_Vec_uint8_t
double_ratchet_descrypt_message (
FFIRatchetState_t * state,
FFIEncryptResult_t const * encrypted);
/** <No documentation available> */
FFIEncryptResult_t *
double_ratchet_encrypt_message (
FFIRatchetState_t * state,
Vec_uint8_t const * plaintext);
typedef struct {
uint8_t idx[32];
} uint8_32_array_t;
/** <No documentation available> */
typedef struct FFIInstallationKeyPair FFIInstallationKeyPair_t;
/** <No documentation available> */
FFIRatchetState_t *
double_ratchet_init_receiver (
uint8_32_array_t shared_secret,
FFIInstallationKeyPair_t const * keypair);
/** <No documentation available> */
FFIRatchetState_t *
double_ratchet_init_sender (
uint8_32_array_t shared_secret,
uint8_32_array_t remote_pub);
/** <No documentation available> */
void
encrypt_result_destroy (
FFIEncryptResult_t * result);
/** <No documentation available> */
void
ffi_c_string_free (
Vec_uint8_t s);
/** <No documentation available> */
void
installation_key_pair_destroy (
FFIInstallationKeyPair_t * keypair);
/** <No documentation available> */
FFIInstallationKeyPair_t *
installation_key_pair_generate (void);
/** <No documentation available> */
uint8_32_array_t
installation_key_pair_public (
FFIInstallationKeyPair_t const * keypair);
/** <No documentation available> */
void
ratchet_state_destroy (
FFIRatchetState_t * state);
#ifdef __cplusplus
} /* extern \"C\" */
#endif
#endif /* __RUST_DOUBLE_RATCHETS__ */