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}