use std::time::{SystemTime, UNIX_EPOCH};
use ring::rand::{SecureRandom, SystemRandom};
pub trait Clock: Send + Sync {
fn now_secs(&self) -> u64;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct SystemClock;
impl Clock for SystemClock {
fn now_secs(&self) -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0)
}
}
pub fn hex(bytes: &[u8]) -> String {
const T: &[u8; 16] = b"0123456789abcdef";
let mut out = String::with_capacity(bytes.len() * 2);
for b in bytes {
out.push(T[(b >> 4) as usize] as char);
out.push(T[(b & 15) as usize] as char);
}
out
}
pub fn unhex(s: &str) -> Option<Vec<u8>> {
let s = s.as_bytes();
if !s.len().is_multiple_of(2) {
return None;
}
let nib = |c: u8| match c {
b'0'..=b'9' => Some(c - b'0'),
b'a'..=b'f' => Some(c - b'a' + 10),
b'A'..=b'F' => Some(c - b'A' + 10),
_ => None,
};
s.chunks(2)
.map(|p| Some(nib(p[0])? << 4 | nib(p[1])?))
.collect()
}
pub fn random_bytes<const N: usize>() -> [u8; N] {
let mut b = [0u8; N];
SystemRandom::new()
.fill(&mut b)
.expect("system randomness unavailable");
b
}
pub fn sha256_hex(data: &[u8]) -> String {
hex(ring::digest::digest(&ring::digest::SHA256, data).as_ref())
}
#[cfg_attr(not(feature = "remote"), allow(dead_code))]
pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
subtle::ConstantTimeEq::ct_eq(a, b).into()
}