General Improvements 4

This commit is contained in:
Alex 2026-08-06 00:15:22 +02:00
commit 5140f4ddc8
Signed by: alex
SSH key fingerprint: SHA256:D1+Ub8o0v4K5y1JNivW8IxEOelqLSvPmUzBbDIoZkRQ

View file

@ -233,26 +233,26 @@ pub fn sign_credential(
Ok(format!("{}.{}", payload_b64, sig_b64)) Ok(format!("{}.{}", payload_b64, sig_b64))
} }
/// Verify and decode a signed credential, returning the claims if valid. /// Verify the cryptographic signature and expiry of a signed credential.
/// ///
/// Checks performed: /// This performs only the pure cryptographic checks that require no external state:
/// 1. Signature verification (HMAC-SHA256) /// 1. Parse the credential format
/// 2. Expiry verification /// 2. Verify HMAC-SHA256 signature
/// 3. Pod identity binding /// 3. Check expiry
/// ///
/// Revocation and attempt-active checks require external state (database) and /// Returns the verified claims on success. The caller is responsible for
/// must be performed by the caller after this returns `Ok`. /// performing persistence-level validation (pod binding, attempt active,
pub fn verify_credential( /// revocation) after this returns `Ok`.
pub fn verify_signature(
credential: &str, credential: &str,
secret: &[u8], secret: &[u8],
expected_pod_id: Uuid,
) -> Result<CredentialClaims, CredentialError> { ) -> Result<CredentialClaims, CredentialError> {
use base64::Engine; use base64::Engine;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use sha2::Sha256; use sha2::Sha256;
let (payload_b64, sig_b64) = SignedCredential::parse(credential) let (payload_b64, sig_b64) =
.ok_or(CredentialError::MalformedPayload)?; SignedCredential::parse(credential).ok_or(CredentialError::MalformedPayload)?;
// Decode payload // Decode payload
let payload_bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD let payload_bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD
@ -276,6 +276,25 @@ pub fn verify_credential(
return Err(CredentialError::Expired); return Err(CredentialError::Expired);
} }
Ok(claims)
}
/// Verify and decode a signed credential, returning the claims if valid.
///
/// Checks performed:
/// 1. Signature verification (HMAC-SHA256)
/// 2. Expiry verification
/// 3. Pod identity binding
///
/// Revocation and attempt-active checks require external state (database) and
/// must be performed by the caller after this returns `Ok`.
pub fn verify_credential(
credential: &str,
secret: &[u8],
expected_pod_id: Uuid,
) -> Result<CredentialClaims, CredentialError> {
let claims = verify_signature(credential, secret)?;
// Check pod binding // Check pod binding
if claims.pod_id != expected_pod_id { if claims.pod_id != expected_pod_id {
return Err(CredentialError::PodMismatch); return Err(CredentialError::PodMismatch);