diff --git a/src/identity/did_key.rs b/src/identity/did_key.rs index b03f80a..07791a0 100644 --- a/src/identity/did_key.rs +++ b/src/identity/did_key.rs @@ -8,11 +8,44 @@ use super::did::DidParseError; const DID_KEY_RE: &str = r"did:key:(?Pz[a-km-zA-HJ-NP-Z1-9]+)"; +// https://github.com/multiformats/multicodec +// 0xed: Ed25519 public key +// 0x01: integer encoding +const MULTICODEC_ED25519_PREFIX: [u8; 2] = [0xed, 0x01]; + #[derive(Clone, Debug, PartialEq)] pub struct DidKey { pub key: Vec, } +#[derive(thiserror::Error, Debug)] +#[error("multicodec error")] +pub struct MulticodecError; + +impl DidKey { + pub fn from_ed25519_key(key: [u8; 32]) -> Self { + let prefixed_key = [ + MULTICODEC_ED25519_PREFIX.to_vec(), + key.to_vec(), + ].concat(); + Self { key: prefixed_key } + } + + pub fn try_ed25519_key(&self) -> Result<[u8; 32], MulticodecError> { + if self.key.len() != 34 { + return Err(MulticodecError); + }; + let mut prefix = [0; 2]; + let mut key = [0; 32]; + prefix.copy_from_slice(&self.key[0..2]); + key.copy_from_slice(&self.key[2..34]); + if prefix.as_ref() != MULTICODEC_ED25519_PREFIX { + return Err(MulticodecError); + }; + Ok(key) + } +} + #[derive(thiserror::Error, Debug)] enum MultibaseError { #[error("invalid base string")] @@ -81,6 +114,8 @@ mod tests { let did_str = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"; let did_key: DidKey = did_str.parse().unwrap(); assert_eq!(did_key.key.len(), 34); // Ed25519 public key + let decoded_key = did_key.try_ed25519_key().unwrap(); + let did_key = DidKey::from_ed25519_key(decoded_key); assert_eq!(did_key.to_string(), did_str); } }