use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine as _;
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
const MULTICODEC_ED25519: [u8; 2] = [0xed, 0x01];
pub fn decode_public_key(did: &str) -> Option<[u8; 32]> {
let encoded = did.strip_prefix("did:key:z")?;
let raw = bs58::decode(encoded).into_vec().ok()?;
if raw.len() != 34 || raw[..2] != MULTICODEC_ED25519 {
return None;
}
let mut key = [0u8; 32];
key.copy_from_slice(&raw[2..]);
Some(key)
}
pub fn b64u_decode(text: &str) -> Option<Vec<u8>> {
let trimmed = text.trim_end_matches('=');
URL_SAFE_NO_PAD.decode(trimmed).ok()
}
pub fn verify(pubkey_did: &str, message: &[u8], signature_b64u: &str) -> bool {
let Some(key_bytes) = decode_public_key(pubkey_did) else {
return false;
};
let Ok(key) = VerifyingKey::from_bytes(&key_bytes) else {
return false;
};
let Some(signature_bytes) = b64u_decode(signature_b64u) else {
return false;
};
let Ok(signature) = Signature::from_slice(&signature_bytes) else {
return false;
};
key.verify(message, &signature).is_ok()
}