Crate zf_zebrachain

Crate zf_zebrachain 

Source
Expand description

Β§πŸ¦“ πŸ”— ZebraChain: A futuristic cryptographic identity system.

ZebraChain is a logged, quantum safe signing protocol designed to replace the long lived asymmetric key pairs used to sign software releases (and to sign other super important stuff).

In short, ZebraChain:

  • Logs each signature in a block chain

  • Changes the keypairs at every signature by including the public key used to sign the current block and the hash of the public key that will be used to sign the next block

  • Is quantum secure because it uses ML-DSA + ed25519 in a hybrid signing construction (as recommended by the ML-DSA authors)

This is a pre-release crate. The API is still being finalized. The 0.0.x releases make no API commitments, nor any commits to the protocol.

However, the dust is settling quickly and it’s a perfect time to jump in and start building experimental applications on top of ZebraChain!

§⚠️ Security Warning

ZebraChain is not yet suitable for production use.

This is a nascent implementation of a yet to be finalized protocol. It’s also built on a quite new Rust implementation of ML-DSA that has its own security warning.

Β§πŸš€ Quickstart

use tempfile;
use zf_zebrachain::{ChainStore, Cursor, Hash, OwnedChainStore, Payload};

// To create a chain and make signatures, you need a directory for your public chain files
// and another directory for your secret chain files:
let chain_dir = tempfile::TempDir::new().unwrap();
let secret_chain_dir = tempfile::TempDir::new().unwrap();

// Use both directories in your OwnedChainStore:
let owned_store = OwnedChainStore::new(chain_dir.path(), secret_chain_dir.path());

// OwnedChainStore.list_chains() will return zero chains (as we haven't created any yet):
assert_eq!(owned_store.list_chains().unwrap(), []);

// A Payload is what you to sign. Currently it's a 64-bit timestamp and a 320-bit hash. To
// create a new chain, you need the first payload that you want to sign:
let payload1 = Payload::new_time_stamped(Hash::compute(b"Message number 1"));

// Lastly, you need a password (or a key from a hardware security module or similar) that will
// be used to encrypt this secret chain:
let password = b"SUPER BAD PASSWORD";
let mut owned_chain = owned_store.generate_chain(&payload1, password).unwrap();
assert_eq!(owned_chain.head().payload, payload1);
assert_eq!(owned_chain.tail().payload, payload1);

// Make another signature like this:
let payload2 = Payload::new_time_stamped(Hash::compute(b"Message number 2"));
owned_chain.sign(&payload2).unwrap();
assert_eq!(owned_chain.head().payload, payload1);
assert_eq!(owned_chain.tail().payload, payload2);

// A chain is identified by its `chain_hash`, which is the hash of the 1st block in the chain:
let chain_hash = *owned_chain.chain_hash();
assert_eq!(chain_hash, owned_chain.head().block_hash);

// OwnedChainStore.list_chains() now shows our expected chain:
assert_eq!(owned_store.list_chains().unwrap(), [chain_hash]);

// Reopen the owned chain and create additional signatures like this:
let mut owned_chain = owned_store.open_chain(&chain_hash, password).unwrap();
let payload3 = Payload::new_time_stamped(Hash::compute(b"Message number 3"));
owned_chain.sign(&payload3).unwrap();
assert_eq!(owned_chain.head().payload, payload1);
assert_eq!(owned_chain.tail().payload, payload3);

// A ChainStore is used for consuming the public side of the chain:
let store = ChainStore::new(chain_dir.path());

// ChainStore.list_chains() likewise shows our expected chain:
assert_eq!(store.list_chains().unwrap(), [chain_hash]);

// Open and fully verify the public chain by the `chain_hash` like this:
let mut chain = store.open_chain(&chain_hash).unwrap();
assert_eq!(chain.head().payload, payload1);
assert_eq!(chain.tail().payload, payload3);

// A Cursor allows you step step forward and backward through a chain:
let mut cursor = Cursor::from_tail(&mut chain);
assert_eq!(cursor.block_state().payload, payload3);
cursor.previous_block().unwrap();
assert_eq!(cursor.block_state().payload, payload2);
cursor.previous_block().unwrap();
assert_eq!(cursor.block_state().payload, payload1);

StructsΒ§

Block
Validate block wire format, extract items from the same.
BlockState
Contains state from current block needed to validate next block, plus the payload.
Chain
Read and write blocks to a file.
ChainIter
Iterate through each Block in a Chain.
ChainStore
Organizes Chain files in a directory.
CheckPoint
Check point a chain for fast reload.
Cursor
Step forward or backward through a Chain, block by block.
EntropyError
Error equivalent to gettrandom::Error.
Hash
Buffer containing the 320-bit (40-byte) BLAKE2b hash, with ConstantTimeEq.
MutBlock
Builds up a new block in a buffer.
MutOwnedBlock
Builds up both public and secret block for new block being signed.
MutSecretBlock
Builds a new SecretBlock up in a buffer.
OwnedBlockState
Combines BlockState and SecretBlockState.
OwnedChain
Sign new blocks in an owned chain.
OwnedChainStore
Used to create new blocks in a chain you own.
Payload
Content to be included in block and signed.
Secret
A 384-bit (48-byte) root secret with ZeroizeOnDrop and ConstantTimeEq.
SecretBlock
Decrypts and validates a secret block.
SecretBlockState
State from this secret block needed to validate the next block, plus the payload.
SecretChain
Save secret chain to non-volatile storage (encrypted and authenticated).
SecretChainHeader
Secret chain header.
SecretChainIter
Iterate through secret blocks contained in a secret chain file.
SecretChainStore
Organizes SecretChain files in a directory.
Seed
Stores secret and next_secret.
SubSecret
Simple buffer with ZeroizeOnDrop and ConstantTimeEq.

EnumsΒ§

BlockError
Error conditions hit when validating a Block.
HexError
Error when trying to decode a hex encoded Hash.
SecretBlockError
Error conditions hit when validating a SecretBlock.
Zbase32Error
Error when trying to decode a Zbase32 encoded Hash.

ConstantsΒ§

BLOCK
Size of the ZebraChain block (4069 bytes).
CONTEXT
Size of context bytes (48 bytes)
DIGEST
Size of hash output digest (45 bytes).
HEXDIGEST
Size of hex-encoded hash (90 bytes).
PAYLOAD
Size of the ZebraChain payload (48 bytes).
SECRET
Size of secrets (48 bytes)
SECRET_BLOCK
Size of the decrypted secret block (292 bytes).
SECRET_BLOCK_AEAD
Size of the encrypted secret block (308 bytes) [this is the size on disk].
SECRET_CHAIN_HEADER
Size of header at start of secret chain (88 bytes).
Z32DIGEST
Size of Zbase32-encoded hash (72 bytes).

FunctionsΒ§

sign_block
Sign a block buffer.

Type AliasesΒ§

SubSecret192
A 192-bit (24-byte) derived secret.
SubSecret256
A 256-bit (32-byte) derived secret.