use std::{fs, io, path::Path};
use nkeys::KeyPair;
use once_cell::sync::Lazy;
use regex::Regex;
use crate::SecureString;
pub(crate) fn user_jwt_from_file(path: &Path) -> io::Result<SecureString> {
let contents = SecureString::from(fs::read_to_string(path)?);
parse_decorated_jwt(&contents).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"cannot parse user JWT from the credentails file",
)
})
}
pub(crate) fn sign_nonce_with_file(nonce: &[u8], path: &Path) -> io::Result<SecureString> {
let contents = SecureString::from(fs::read_to_string(path)?);
let nkey = parse_decorated_nkey(&contents).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"cannot parse nkey from the credentails file",
)
})?;
let key_pair =
KeyPair::from_seed(&nkey).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let sig = key_pair
.sign(nonce)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
Ok(SecureString::from(base64_url::encode(&sig)))
}
static USER_CONFIG_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}\r?\n))")
.unwrap()
});
fn parse_decorated_jwt(contents: &SecureString) -> Option<SecureString> {
let capture = USER_CONFIG_RE.captures_iter(contents).next()?;
Some(SecureString::from(capture[1].to_string()))
}
fn parse_decorated_nkey(contents: &SecureString) -> Option<SecureString> {
let capture = USER_CONFIG_RE.captures_iter(contents).nth(1)?;
Some(SecureString::from(capture[1].to_string()))
}