Expand description
🛡️ Bitwark: Binary Bulwark in Rust
Bitwark is a cryptographic Rust library (used ring, ed25519-dalek), designed to facilitate secure digital interactions through a meticulous amalgamation of lightweight binary JWT tokens, dynamic key rotation, and strategic salt functionalities, all embedded in a minimalistic API. Through Bitwark, developers can seamlessly perform crucial security operations, such as key and salt generation, payload signing, and integrity message verification, all whilst ensuring optimal performance and security in their applications.
🚀 Getting Started
Engage in a fortified cryptographic experience with Bitwark, utilizing functionalities like secure payload creation, signature encoding, and strategic key rotation with simplicity and efficacy.
🔐 Key Features:
- Binary Signed Payload: Compact binary encoding of signed payload (similar to JWT)
- Default Cryptography: Bitwark by default uses EdDSA for signing and verifying with SHA3-384 (EdDSA_SHA3-384).
- Rotation Easily rotate keys and salts, ensuring your application adapts to the dynamic security landscape.
- Salting: Random data injection to increase entropy and slow brute force attacks.
- Lightweight: Minimal overhead, ensuring optimal performance even in high-throughput scenarios.
Signed Payload decoded as binary (alternative to JWT)
#[derive(Serialize,Deserialize)]
pub struct Claims {
pub permissions: Vec<String>,
}
// Generate an EdDSA key pair with a validity period of 10 minutes and a salt with a validity of 5 minutes.
let exp_key = AutoExpiring::<EdDsaKey>::generate(
Duration::minutes(10)
).unwrap();
let exp_salt = AutoExpiring::<Salt64>::generate(
Duration::minutes(5)
).unwrap();
// Instantiate a token with specified claims.
let claims = Claims { permissions: vec!["users:read".to_string(), "users:write".to_string()]};
let token = ExpiringSigned::<Claims>::new(Duration::seconds(120), claims).unwrap();
// Create a binary encoding of the token, signed with the key and salt.
let signed_token_bytes = token.encode_and_sign_salted(&exp_salt, &*exp_key)
.expect("Failed to sign token");
// Decode the token and verify its signature and validity.
let decoded_token = ExpiringSigned::<Claims>::decode_and_verify_salted(
&signed_token_bytes, &exp_salt, &*exp_key
).expect("Failed to decode a token");
assert_eq!(2, decoded_token.permissions.len(), "Failed to find 2 permissions");Key Generation and Management
Bitwark enables the generation and rotation of cryptographic keys, ensuring persistent security through periodic key renewals.
// Generate an EdDSA key pair.
let key = EdDsaKey::generate().unwrap();Key Rotation for Enhanced Security
Effortlessly manage and rotate your keys, maintaining a fresh and secure application environment through time-based key expiration and renewals.
let key = EdDsaKey::generate().unwrap();
let mut expiring_key = AutoExpiring::new(Duration::seconds(10), key).unwrap();
if expiring_key.is_expired() {
// update key internally
expiring_key.rotate().unwrap();
}Payload Creation and Management
Construct, encode, and decode secure payloads, ensuring message integrity through signature verification.
let key = EdDsaKey::generate().unwrap();
// Construct a payload.
let payload = SignedPayload::<String>::new("A signed message".to_string());
// Encode the payload.
let signed_payload_bytes = payload.encode_and_sign(&key).unwrap();
// Decode, verifying the signature.
let decoded_payload = SignedPayload::<String>::decode_and_verify(&signed_payload_bytes, &key).unwrap();
assert_eq!(*decoded_payload, *payload);Salting
The Salt[N] struct can be utilized to generate random salts which are pivotal in
cryptographic operations to safeguard against various forms of attack and to ensure
that identical inputs do not produce identical outputs across different users or sessions.
Salt variants
Salt126- 126 bytes lengthSalt64Salt32Salt16Salt12
use bitwark::salt::Salt64;
use bitwark::Generator;
let salt1 = Salt64::generate().unwrap();
let salt2 = Salt64::generate().unwrap();
// Assert that different generated salts are not equal.
// In cryptographic operations, unique salts are pivotal to secure storage and transmission.
assert_ne!(*salt1, *salt2, "Salts should be unique across generations.");Salts can also be seamlessly integrated into rotation operations, frequently refreshing them to enhance security further. This is particularly valuable in contexts where the same data might be encrypted multiple times, ensuring each instance yields different ciphertext.
Example with Rotation (Assuming Expiring is a structure which utilizes the Rotation trait):
use bitwark::{salt::Salt64, exp::AutoExpiring, keys::ed::EdDsaKey, Rotation, Generator};
use bitwark::payload::SignedPayload;
use chrono::Duration;
// Make a new salt.
let salt = Salt64::generate().unwrap();
// Make a salt that lasts for 10 seconds.
let mut expiring_salt = AutoExpiring::<Salt64>::new(Duration::seconds(10), salt).unwrap();
// Change the salt if it's too old.
if expiring_salt.is_expired() {
expiring_salt.rotate().expect("Salt rotation failed.");
}
// Make a key that lasts for 120 seconds.
let key = AutoExpiring::<EdDsaKey>::generate(Duration::seconds(120)).unwrap();
// Make a payload for signing
let payload = SignedPayload::<String>::new("Hello, world!".to_string());
// Combine the message and a special code (signature) into one piece.
let signature_bytes = payload.encode_and_sign_salted(&expiring_salt, &*key).expect("Failed to encode");
// Separate the message and the signature, checking they're valid.
let decoded_result = SignedPayload::<String>::decode_and_verify_salted(&signature_bytes, &expiring_salt, &*key);
assert!(decoded_result.is_ok());Using salts and rotating them regularly strengthens security by ensuring that even repeated data or credentials produce different hashes or ciphertexts across different instances or sessions.
Re-exports
pub use error::BwError;
Modules
Traits
- The
Generatortrait defines a common interface for types that require a generation phase, typically resulting in the instantiation of a unique or random state. - The
Rotationtrait encapsulates the best practice of rotating cryptographic or sensitive materials, minimizing the potential impact of key compromise or algorithmic predictions.