use base64::Engine;
use serde_json::{Value, json};
use crate::keystore::KeyStore;
pub fn build_did_document(store: &KeyStore, base_url: &str, key_id: &str) -> anyhow::Result<Value> {
if !store.has_key(key_id) {
store.generate_key(key_id)?;
}
let current = store.load_key(key_id)?;
let hostname = base_url
.trim_start_matches("https://")
.trim_start_matches("http://");
let did = format!("did:web:{}", hostname.replace(':', "%3A"));
let b64 = base64::engine::general_purpose::URL_SAFE_NO_PAD;
let primary_vm_id = format!("{did}#key-1");
let primary_pub_b64 = b64.encode(current.verifying_key.as_bytes());
let mut verification_methods = vec![json!({
"id": primary_vm_id,
"type": "JsonWebKey2020",
"controller": did,
"publicKeyJwk": {
"kty": "OKP",
"crv": crate::jws::algorithm::ED25519_CRV,
"x": primary_pub_b64
}
})];
let archived: Vec<_> = store
.load_archived_keys(key_id)
.into_iter()
.filter(|k| !k.revoked)
.collect();
for (idx, archived_key) in archived.iter().enumerate() {
let vm_id = format!("{did}#key-{}", idx + 2);
let pub_b64 = b64.encode(archived_key.verifying_key.as_bytes());
verification_methods.push(json!({
"id": vm_id,
"type": "JsonWebKey2020",
"controller": did,
"publicKeyJwk": {
"kty": "OKP",
"crv": crate::jws::algorithm::ED25519_CRV,
"x": pub_b64
}
}));
}
let assertion_methods: Vec<String> = verification_methods
.iter()
.filter_map(|vm| vm["id"].as_str().map(String::from))
.collect();
let doc = json!({
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"id": did,
"verificationMethod": verification_methods,
"authentication": [primary_vm_id],
"assertionMethod": assertion_methods
});
Ok(doc)
}