pray-core 1.10.0

Core library for Prayfile, the package manager for the language placed before inference
Documentation
use super::support::current_unix_timestamp;
use crate::hashing::sha256_prefixed;
use crate::{PrayError, PrayResult};

pub(super) const AUTH_CHALLENGE_TTL_SECONDS: u64 = 5 * 60;
pub(super) const VERIFICATION_CODE_TTL_SECONDS: u64 = 15 * 60;
pub(super) const SESSION_TTL_SECONDS: u64 = 30 * 24 * 60 * 60;
pub(super) const PUBLISH_TOKEN_TTL_SECONDS: u64 = 90 * 24 * 60 * 60;
pub(super) const MAX_VERIFICATION_ATTEMPTS: u32 = 5;
pub(super) const VERIFICATION_FAILED: &str = "verification failed";

pub(super) fn generate_auth_challenge(_kind: &str, _subject: &str) -> PrayResult<String> {
    random_secret("challenge")
}

pub(super) fn generate_verification_code() -> PrayResult<String> {
    random_secret("verify")
}

pub(super) fn generate_session_token() -> PrayResult<String> {
    random_secret("session")
}

pub(super) fn generate_publish_token() -> PrayResult<String> {
    random_secret("publish")
}

pub(super) fn stored_token(token: &str) -> String {
    sha256_prefixed(token.as_bytes())
}

pub(super) fn constant_time_eq(left: &str, right: &str) -> bool {
    let left_bytes = left.as_bytes();
    let right_bytes = right.as_bytes();
    if left_bytes.len() != right_bytes.len() {
        return false;
    }
    let mut difference = 0u8;
    for (left_byte, right_byte) in left_bytes.iter().zip(right_bytes.iter()) {
        difference |= left_byte ^ right_byte;
    }
    difference == 0
}

pub(super) fn record_expired(created_at: u64, ttl_seconds: u64) -> PrayResult<bool> {
    Ok(current_unix_timestamp()?.saturating_sub(created_at) > ttl_seconds)
}

fn random_secret(domain: &str) -> PrayResult<String> {
    let mut bytes = [0u8; 32];
    fill_random(&mut bytes)?;
    let mut payload = domain.as_bytes().to_vec();
    payload.extend_from_slice(&bytes);
    Ok(sha256_prefixed(&payload))
}

fn fill_random(bytes: &mut [u8]) -> PrayResult<()> {
    getrandom::fill(bytes).map_err(|_| {
        PrayError::Resolution("operating system random source unavailable".to_string())
    })
}