df_share/lib.rs
1//! # df-share: Secret Sharing
2//!
3//! This module provides a straightforward API to securely exchange a secret between two parties (a client and a server) using ephemeral Diffie-Hellman keys.
4//! The server encrypts the secret in such a way that only the requesting client can decrypt it, assuming both sides derive the same shared secret key.
5//!
6//! ## Basic Usage
7//!
8//! 1. **Client creates an ephemeral key pair** via [`EphemeralClient::new()`].
9//! - Call [`EphemeralClient::sendable()`] to retrieve a tuple: a request object and a `decryptor`.
10//! 2. **Server receives the request**, creates its own ephemeral key pair via [`EphemeralServer::new()`], and calls [`EphemeralServer::encrypt_secret()`] to produce a response containing the encrypted secret.
11//! 3. **Client decrypts the response** with the `decryptor` it previously obtained.
12//!
13//! ### Example
14//!
15//! ```rust
16//! use df_share::{EphemeralClient, EphemeralServer};
17//! use df_share::error::Unspecified;
18//! # fn example() -> Result<(), Unspecified> {
19//! // Client side
20//! let client = EphemeralClient::new()?;
21//! let (req, decryptor) = client.sendable();
22//!
23//! let res;
24//! let secret = "MyVerySecretPrivateKey010101010";
25//!
26//! // Server side
27//! {
28//! let server = EphemeralServer::new()?;
29//! res = server.encrypt_secret(&req, secret.as_bytes())?;
30//! }
31//!
32//! // Client side again: decrypt the server's response
33//! let decrypted_secret = decryptor.decrypt(&res)?;
34//!
35//! assert_eq!(secret.as_bytes(), &decrypted_secret);
36//! # Ok(())
37//! # }
38//! ```
39//!
40//! **Important Note**: Because the server generates an ephemeral key pair each time, there's no built-in guarantee of the server's identity. If you need server authentication, you must maintain long-term server key material and pin the server public key on the client or use HTTPS/TLS with certificate validation.
41mod art;
42mod client;
43mod server;
44pub use art::generate_ascii_art;
45pub(crate) mod shared;
46
47// api
48pub use client::{ClientReq, EphemeralClient, ResponseDecryptor};
49pub use server::{EphemeralServer, ServerEncryptedRes};
50// re-export ring error
51pub mod error {
52 pub use ring::error::Unspecified;
53}
54// utility
55pub use shared::{from_hex_str, to_hex_str};
56
57#[cfg(test)]
58mod test {
59 use super::*;
60 use client::EphemeralClient;
61 use ring::error::Unspecified;
62 use server::EphemeralServer;
63
64 #[test]
65 fn test_share_secret() -> Result<(), Unspecified> {
66 // client side
67 let client = EphemeralClient::new()?;
68 let (req, decryptor) = client.sendable();
69
70 let res;
71 let secret = "MyVerySecretPrivateKey";
72 {
73 // server side
74 let server = EphemeralServer::new()?;
75 res = server.encrypt_secret(&req, secret.as_bytes())?;
76 }
77
78 // client side
79 let decrypted_secret = decryptor.decrypt(&res)?;
80
81 assert_eq!(secret.as_bytes(), &decrypted_secret);
82 assert!(decrypted_secret != res.ciphertext);
83 Ok(())
84 }
85}