use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine as _;
use sha2::{Digest, Sha256};
pub fn code_challenge_s256(verifier: &str) -> String {
URL_SAFE_NO_PAD.encode(Sha256::digest(verifier.as_bytes()))
}
pub fn verify_s256(verifier: &str, challenge: &str) -> bool {
let computed = code_challenge_s256(verifier);
let (a, b) = (computed.as_bytes(), challenge.as_bytes());
if a.len() != b.len() {
return false;
}
let mut acc = 0u8;
for (x, y) in a.iter().zip(b) {
acc |= x ^ y;
}
acc == 0
}
pub fn verifier_is_valid(verifier: &str) -> bool {
(43..=128).contains(&verifier.len())
&& verifier
.bytes()
.all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'.' | b'_' | b'~'))
}
#[cfg(test)]
#[path = "tests/pkce.rs"]
mod tests;