Include the key-rotater project in the monorepo

This commit is contained in:
Z. Charles Dziura 2025-03-18 13:45:11 -04:00
parent 878ff48d95
commit 42d2705a84
4 changed files with 100 additions and 0 deletions

1
key-rotater/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

10
key-rotater/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "debt-pirate-key-rotater"
version = "0.1.0"
edition = "2021"
[dependencies]
base64 = "0.22.1"
clap = { version = "4.5", features = ["derive"] }
humantime = "2.1"
pasetors = "0.7"

9
key-rotater/README.md Normal file
View file

@ -0,0 +1,9 @@
# Debt Pirate Key Rotater
Creates new PASETO keys for use in the API
## Example
```
$ dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | xargs cargo run --
```

80
key-rotater/src/main.rs Normal file
View file

@ -0,0 +1,80 @@
use std::{
env,
io::{self, BufRead, Write},
process,
time::{Duration, SystemTime},
};
use base64::prelude::*;
use humantime::format_rfc3339_seconds;
use pasetors::{
keys::SymmetricKey,
paserk::{FormatAsPaserk, Id},
version4::V4,
};
fn main() {
let encoded_secret = read_secret();
let secret = if let Ok(secret) = decode_secret(encoded_secret) {
secret
} else {
eprintln!("Not a valid 32-byte, base64 encoded string.");
process::exit(1);
};
let (id, key) = generate_local_key(secret.as_slice());
let mut id_string = String::new();
id.fmt(&mut id_string).unwrap();
let one_year: Duration = Duration::from_secs_f64(60_f64 * 60_f64 * 24_f64 * 365.25_f64);
let expiration = format_rfc3339_seconds(SystemTime::now() + one_year);
println!("ID: {id_string}\nKey: {key}\nExpiration: {expiration}");
}
fn read_secret() -> String {
let secret_arg = env::args().skip(1).last();
let secret = if let Some(secret) = secret_arg {
secret
} else {
print!("Enter a 32-byte, base64 encoded string: ");
let _ = io::stdout().flush();
let mut buffer = String::with_capacity(32);
let stdin = io::stdin();
stdin.lock().read_line(&mut buffer).unwrap();
buffer
.strip_suffix("\r\n")
.or(buffer.strip_suffix("\n"))
.map(|buffer| buffer.to_owned())
.unwrap_or(buffer)
};
secret
}
fn decode_secret(secret: String) -> Result<Vec<u8>, ()> {
BASE64_STANDARD
.decode(secret)
.map_err(|_| ())
.and_then(|secret| {
if secret.len() != 32 {
Err(())
} else {
Ok(secret)
}
})
}
fn generate_local_key(secret: &[u8]) -> (Id, String) {
let key = SymmetricKey::<V4>::from(secret).unwrap();
let mut serialized_key = String::with_capacity(54);
let _ = key.fmt(&mut serialized_key);
let id = Id::from(&key);
(id, serialized_key)
}