Crates.io | bitwark |
lib.rs | bitwark |
version | 2.0.1 |
source | src |
created_at | 2023-10-06 23:38:25.80102 |
updated_at | 2024-10-29 22:02:16.608095 |
description | Empowering secure digital interactions with robust binary token management and dynamic rolling keys |
homepage | https://github.com/Nawy/bitwark |
repository | https://github.com/Nawy/bitwark |
max_upload_size | |
id | 995704 |
size | 75,650 |
Provides robust security for Rust applications through compact binary tokens and automated cryptographic defenses.
Bitwark is your go-to library for enhancing security in Rust applications. It offers a streamlined, bandwidth-friendly version of JSON Web Tokens (JWTs) and includes features like automatic key rotation and data salting to bolster your app's defenses.
Explore the secure features of Bitwark for your Rust applications:
Imagine you have a structure you wish to sign and send back to the user:
#[derive(Serialize, Deserialize, Clone)]
pub struct Token {
pub user_id: u32,
pub permissions: Vec<String>,
}
First, generate a key that expires after 10 minutes, though you can set it for days, months, or years as needed. For a non-expiring key, simply use EdDsaKey::generate()
:
let exp_key = AutoExpiring::<EdDsaKey>::generate(
Duration::minutes(10)
).unwrap();
Next, create the token. SaltyExpiringSigned
adds a default 64-byte salt and includes an expiration time:
let token_object = Token { user_id: 123, permissions: vec!["Read".to_string(), "Write".to_string()] };
let token = SaltyExpiringSigned::<Token>::new(
chrono::Duration::minutes(10),
token_object
).unwrap();
Finally, prepare the token for the client. You can return it as bytes or convert it to base64:
let token_bytes: Vec<u8> = token.encode_and_sign(&*exp_key).unwrap();
When the user provides this token to your service, verifying it is straightforward:
let token = SaltyExpiringSigned::<Token>::decode_and_verify(&token_bytes, &*exp_key).unwrap();
if token.permissions.contains(&String::from("Read")) {
// Proceed with the user's request
}
use bitwark::{
exp::AutoExpiring,
signed_exp::ExpiringSigned,
salt::Salt64,
keys::{ed::EdDsaKey},
};
use serde::{Serialize, Deserialize};
use chrono::Duration;
#[derive(Serialize, Deserialize)]
pub struct Claims {
pub permissions: Vec<String>,
}
// Generate an EdDSA key pair and salt with a validity period
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 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"
);
use bitwark::{payload::SignedPayload, keys::ed::EdDsaKey, keys::CryptoKey, Generator};
use chrono::Duration;
// creating a key
let key = EdDsaKey::generate()?;
// Rotating key
let mut expiring_key = Expiring<EdDsaKey>::new(Duration::seconds(10), key);
if expiring_key.has_expired() {
expiring_key.roll()?;
}
// Creating a payload
let payload = SignedPayload::<String>::new("A signed message".to_string());
// Encode the payload with signature based on the expiring key
let signed_payload_bytes = payload.encode_and_sign(&expiring_key)?;
// Decode the signed payload with verifying signature with payload's integrity
let decoded_payload = SignedPayload::<String>::decode_and_verify(&signed_payload_bytes, &expiring_key)?;
assert_eq!(*decoded_payload, *payload);
use bitwark::{
salt::Salt64,
exp::AutoExpiring,
key::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.has_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 message and signature into one piece.
let signature_bytes = payload.encode_and_sign_salted(
&expiring_salt, &*key
).expect("Failed to encode");
// Separate message and signature, verifying validity.
let decoded_result =
SignedPayload::<String>::decode_and_verify_salted(
&signature_bytes, &expiring_salt, &*key
);
assert!(decoded_result.is_ok());
In today's digital landscape, security must not come at the expense of performance. Bitwark addresses this challenge by:
We believe in the power of community, and Bitwark thrives on contributions from developers like you:
Bitwark is licensed under the MIT License or Apache-2.0 to ensure it remains accessible for all developers.