1use codec_multibase::multibase_to_bytes;
6use codec_multicodec::{lookup_codec_prefix, KeyMaterialKind, VARIABLE_KEY_LENGTH};
7
8use crate::error::MultikeyError;
9
10pub struct ParsedMultikey {
12 pub codec_name: &'static str,
14 pub alg: &'static str,
16 pub public_key: Vec<u8>,
18 pub key_length: usize,
20}
21
22pub fn parse_multikey(multibase_key: &str) -> Result<ParsedMultikey, MultikeyError> {
27 if multibase_key.len() < 2 {
28 return Err(MultikeyError::InvalidMultibase);
29 }
30
31 let raw = multibase_to_bytes(multibase_key).map_err(|_| MultikeyError::InvalidMultibase)?;
33
34 if raw.len() < 2 {
35 return Err(MultikeyError::DecodedTooShort(raw.len()));
36 }
37
38 let found = lookup_codec_prefix(&raw).ok_or(MultikeyError::UnknownCodecPrefix)?;
40
41 if found.key_material != KeyMaterialKind::PublicKey {
42 return Err(MultikeyError::UnknownCodecPrefix);
43 }
44
45 let public_key = raw[found.codec.len()..].to_vec();
46
47 if found.key_length == VARIABLE_KEY_LENGTH && public_key.is_empty() {
49 return Err(MultikeyError::KeyLengthMismatch {
50 codec_name: found.name,
51 expected: found.key_length,
52 actual: public_key.len(),
53 });
54 }
55
56 if found.key_length != VARIABLE_KEY_LENGTH && public_key.len() != found.key_length {
57 return Err(MultikeyError::KeyLengthMismatch {
58 codec_name: found.name,
59 expected: found.key_length,
60 actual: public_key.len(),
61 });
62 }
63
64 Ok(ParsedMultikey {
65 codec_name: found.name,
66 alg: found.alg,
67 public_key,
68 key_length: found.key_length,
69 })
70}