use std::collections::{HashMap, HashSet};
use anyhow::Result;
use ed25519_dalek::VerifyingKey;
use super::did;
#[derive(Default, Clone)]
pub struct TrustStore {
keys: HashSet<[u8; 32]>,
status_lists: HashMap<String, Vec<u8>>,
require_status_lists: bool,
}
pub(crate) fn status_bit(bits: &[u8], index: u64) -> bool {
usize::try_from(index / 8)
.ok()
.and_then(|byte_idx| bits.get(byte_idx))
.is_some_and(|byte| byte & (1 << (index % 8)) != 0)
}
impl TrustStore {
pub fn new() -> Self {
Self::default()
}
pub fn trust_key(&mut self, key: &VerifyingKey) -> &mut Self {
self.keys.insert(key.to_bytes());
self
}
pub fn trust_did(&mut self, did_key: &str) -> Result<&mut Self> {
let pk = did::ed25519_from_did_key(did_key)?;
self.keys.insert(pk);
Ok(self)
}
pub fn trust_did_jwk(&mut self, did_jwk: &str) -> Result<&mut Self> {
let pk = did::ed25519_from_did_jwk(did_jwk)?;
self.keys.insert(pk);
Ok(self)
}
pub fn trusting_key(key: &VerifyingKey) -> Self {
let mut s = Self::new();
s.trust_key(key);
s
}
pub fn trusting_did(did_key: &str) -> Result<Self> {
let mut s = Self::new();
s.trust_did(did_key)?;
Ok(s)
}
pub fn is_trusted(&self, key: &VerifyingKey) -> bool {
self.keys.contains(&key.to_bytes())
}
pub fn trust_status_list(&mut self, credential_url: &str, bits: Vec<u8>) -> &mut Self {
self.status_lists.insert(credential_url.to_string(), bits);
self
}
pub fn is_revoked(&self, credential_url: &str, index: u64) -> Option<bool> {
self.status_lists
.get(credential_url)
.map(|bits| status_bit(bits, index))
}
pub fn require_status_lists(&mut self, required: bool) -> &mut Self {
self.require_status_lists = required;
self
}
pub fn requires_status_lists(&self) -> bool {
self.require_status_lists
}
pub fn is_empty(&self) -> bool {
self.keys.is_empty()
}
pub fn len(&self) -> usize {
self.keys.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
use ed25519_dalek::SigningKey;
fn key() -> SigningKey {
SigningKey::from_bytes(&rand::random())
}
#[test]
fn empty_trusts_nothing() {
let store = TrustStore::new();
assert!(store.is_empty());
assert!(!store.is_trusted(&key().verifying_key()));
}
#[test]
fn trusts_added_key_only() {
let trusted = key();
let other = key();
let store = TrustStore::trusting_key(&trusted.verifying_key());
assert!(store.is_trusted(&trusted.verifying_key()));
assert!(!store.is_trusted(&other.verifying_key()));
assert_eq!(store.len(), 1);
}
#[test]
fn trust_via_did_roundtrips() {
let k = key();
let did = did::did_key_from_ed25519(&k.verifying_key().to_bytes());
let store = TrustStore::trusting_did(&did).unwrap();
assert!(store.is_trusted(&k.verifying_key()));
}
}