zf_zebrachain/
lib.rs

1#![deny(missing_docs)]
2
3//! 🦓 🔗 ZebraChain: A futuristic cryptographic identity system.
4//!
5//! ZebraChain is a logged, quantum safe signing protocol designed to replace the long lived
6//! asymmetric key pairs used to sign software releases (and to sign other super important stuff).
7//!
8//! This is a pre-release crate. The API is still being finalized.
9//!
10//! # ⚠️ Security Warning
11//!
12//! ZebraChain is not yet suitable for production use.
13//!
14//! This is a nascent implementation of a yet to be finalized protocol. It's also built an quite
15//! new Rust implementations of [ML-DSA] and [SLH-DSA].
16//!
17//! # Quickstart
18//!
19//! ```
20//! use tempfile;
21//! use zf_zebrachain::{ChainStore, OwnedChainStore, Hash, Payload, generate_secret};
22//!
23//! // Chains are just files in a directory (for now). To get started you need a directory for
24//! // your public chain files and a `ChainStore`:
25//! let chain_dir = tempfile::TempDir::new().unwrap();
26//! let store = ChainStore::new(chain_dir.path());
27//!
28//! // To create signatures in a chain that you own, you also need a directory for your secret
29//! // chain files and a secret storage key that will be used to encrypt them:
30//! let secret_chain_dir = tempfile::TempDir::new().unwrap();
31//! let storage_secret = generate_secret().unwrap(); // Uses getrandom::fill()
32//! let mystore = OwnedChainStore::build(
33//!     chain_dir.path(), secret_chain_dir.path(), storage_secret
34//! );
35//!
36//! // A Payload is what you to sign. Currently it's a 64-bit timestamp and a 256-bit hash. To
37//! // create a new chain, you need the first payload that you want to sign:
38//! let p1 = Payload::new(123, Hash::from_bytes([42; 32]));
39//!
40//! // To create a new chain, you also need some initial entropy, which is used to derive the seeds
41//! // for the 1st and 2nd ML-DSA/ed25519 hybrid keypairs.
42//! let initial_entropy = generate_secret().unwrap();
43//!
44//! // Create a chain, the first block of which will contain the signed payload. The first block
45//! // is signed with the 1st keypair, but the hash of the public key of the 2nd keypair is
46//! // included in the 1st block. This is the forward contract for the keypair that will be used
47//! // to sign the next block.
48//! let mut mychain = mystore.create_chain(&initial_entropy, &p1).unwrap();
49//! assert_eq!(mychain.tail().payload, p1);
50//!
51//! // Let us sign another payload. Each signatures requires new entropy, which is mixed into the
52//! // the secret chain state using a keyed hash. This latest seed will be used to create a 3rd
53//! // keypair, and the hash of its public key is included this block. The 2nd block is signed with
54//! // the 2nd keypair created above.
55//! let p2 = Payload::new(456, Hash::from_bytes([69; 32]));
56//! let new_entropy = generate_secret().unwrap();
57//! mychain.sign(&new_entropy, &p2);
58//! assert_eq!(mychain.tail().payload, p2);
59//!
60//! // A chain is identified by its `chain_hash`, which is the hash of the 1st block in the chain:
61//! let chain_hash = mychain.chain_hash();
62//!
63//! // We can now open that chain from the public chain store, which will fully validate the chain
64//! // and set the tail at the latest block:
65//! let chain = store.open_chain(&chain_hash).unwrap();
66//! assert_eq!(chain.tail().payload, p2);
67//! ```
68//!
69//! [ML-DSA]: https://github.com/RustCrypto/signatures/tree/master/ml-dsa
70//! [SLH-DSA]: https://github.com/RustCrypto/signatures/tree/master/slh-dsa
71
72mod always;
73mod block;
74mod chain;
75mod errors;
76mod fsutil;
77mod ownedblock;
78mod ownedchain;
79mod payload;
80mod pksign;
81mod secretblock;
82mod secretchain;
83mod secretseed;
84
85#[cfg(test)]
86pub mod testhelpers;
87
88pub use always::{BLOCK, DIGEST, PAYLOAD};
89pub use block::{Block, BlockResult, BlockState, MutBlock};
90pub use chain::{Chain, ChainIter, ChainStore, CheckPoint};
91pub use errors::{BlockError, SecretBlockError};
92pub use ownedblock::{MutOwnedBlock, OwnedBlockState, sign};
93pub use ownedchain::{OwnedChain, OwnedChainStore};
94pub use payload::Payload;
95pub use secretblock::{MutSecretBlock, SecretBlock, SecretBlockState};
96pub use secretchain::{SecretChain, SecretChainIter, SecretChainStore};
97pub use secretseed::{EntropyError, Secret, Seed, generate_secret};
98
99pub use blake3::Hash;