attrkey 0.1.0-alpha.2

Pure Rust implementation of a Selection-Sensitive Attribute-Based Key Derivation Scheme.
Documentation
//! A pure Rust implementation of Selection-Sensitive Attribute-Based Key
//! Derivation, providing a novel scheme where cryptographic keys are derived
//! from a collection of attributes, with sensitivity to selection within the
//! collection.
//!
//! An **attribute** is a piece of data that contributes to key derivation.
//! A collection of attributes is first hardened using a
//! [password hasher](password_hash::PasswordHasher), then organised into a
//! keyspace from which attribute-based keys can be selected.
//!
//! A **keyspace** consists of:
//! - A collection of attribute values hardened through parallel password
//! hashing.
//! - Proof-of-work constraint.
//! - Optional application context for domain separation.
//!
//! Key derivation requires selecting a subset of attribute indices, which
//! partitions the collection into two sets: selected and remaining attributes.
//! These are each concatenated to form keying and antikeying material for an
//! [annihilative pair](annihilation::AnnihlKey::new_pair), where selected
//! attributes become keying material and remaining attributes become
//! antikeying material. The derived annihilative pair's
//! [annihilation key](annihilation::AnnihlKey::to_annihilation) is computed
//! and used as a [seed for RNG expansion](rand_core::SeedableRng::from_seed)
//! to produce the final derived key under this scheme.
//!
//! Derived keys depend on both which attributes are selected and which are
//! not. Different selections produce cryptographically independent keys, even
//! when there is overlap in selection. Per-attribute password hashing makes
//! brute-force attacks computationally expensive, and the derived key's
//! dependence on all attributes prevents an attacker with knowledge of
//! attribute selection from optimising by discarding remaining attributes.
//!
//! The requirement to select at least one attribute, but not all attributes,
//! ensures that both partition sets are non-empty and the annihilative pair
//! can be constructed.
//!
//! # Example
//! ```
//! use attrkey::Attributes;
//! use chacha20::ChaCha20Rng;
//! use scrypt::{Params, Scrypt};
//!
//! fn main() {
//!     let arr = vec![
//!         b"Pigs on the Wing I".to_vec(),
//!         b"Dogs".to_vec(),
//!         b"Pigs (Three Different Ones)".to_vec(),
//!         b"Sheep".to_vec(),
//!         b"Pigs on the Wing II".to_vec(),
//!     ];
//!
//!     let params = Params::new(4, 8, 1).unwrap();
//!     let scrypt = Scrypt::new_with_params(params);
//!
//!     // Create a collection of attributes with Scrypt and ChaCha20
//!     let attributes = Attributes::<_, ChaCha20Rng>::new(arr, scrypt)
//!         .expect("valid attributes should produce collection");
//!
//!     // Harden attributes into a keyspace
//!     let keyspace = attributes
//!         .harden(4, None)
//!         .expect("scrypt is a valid password hasher for hardening");
//!
//!     // Derive keys from two selections within the same keyspace
//!     let selection_1 = vec![0, 2, 4];
//!     let selection_2 = vec![1, 3];
//!
//!     let dk = keyspace
//!         .derive_key(&selection_1, None)
//!         .expect("selection is valid");
//!
//!     let mut dst = [0u8; 32];
//!     keyspace
//!         .derive_key_into(&selection_2, &mut dst)
//!         .expect("selection is valid");
//!
//!     // Different selections produce different keys
//!     assert_ne!(dk, dst);
//! }
//! ```
mod attributes;
mod errors;
mod keyspace;

pub use attributes::Attributes;
pub use errors::AttrkeyError;
pub use keyspace::Keyspace;