key_resolver/
ed25519_verification_key2020.rs1use fi_common::error::Error;
2
3use crate::common::{KeyPair, VerificationKey};
4
5pub(crate) const SUITE_ID: &str = "Ed25519VerificationKey2020";
6pub(crate) const SUITE_CONTEXT: &str = "https://w3id.org/security/suites/ed25519-2020/v1";
7
8const MULTIBASE_BASE58BTC_HEADER: &str = "z";
10const MULTICODEC_ED25519_PUB_HEADER: [u8; 2] = [0xed, 0x01];
12const MULTICODEC_ED25519_PRIV_HEADER: [u8; 2] = [0xed, 0x01];
14
15pub struct Ed25519VerificationKey2020 {
16 _type: String,
17 id: Option<String>,
18 controller: Option<String>,
19 public_key_multibase: String,
20 private_key_multibase: Option<String>,
21 revoked: bool,
22}
23
24impl Ed25519VerificationKey2020 {
25 pub fn new(
26 controller: Option<String>,
27 public_key_multibase: String,
28 private_key_multibase: Option<String>,
29 fingerprint: Option<String>,
30 ) -> Result<Self, Error> {
31 if !Ed25519VerificationKey2020::is_valid_key_header(
32 &public_key_multibase,
33 &MULTICODEC_ED25519_PUB_HEADER,
34 ) {
35 return Err(Error::new(
36 format!(
37 "'publicKeyMultibase' has invalid header bytes: '{}'.",
38 public_key_multibase
39 )
40 .as_str(),
41 ));
42 }
43
44 if private_key_multibase.is_some()
45 && !Ed25519VerificationKey2020::is_valid_key_header(
46 &private_key_multibase.clone().unwrap(),
47 &MULTICODEC_ED25519_PRIV_HEADER,
48 )
49 {
50 return Err(Error::new(
51 format!(
52 "'publicKeyMultibase' has invalid header bytes: '{}'.",
53 private_key_multibase.unwrap()
54 )
55 .as_str(),
56 ));
57 }
58
59 let mut id: Option<String> = None;
60 if controller.is_some() && fingerprint.is_some() {
61 let ctrler = controller.clone().unwrap();
62 let fprint = fingerprint.clone().unwrap();
63 id = Some(format!("{}#{}", ctrler, fprint));
64 }
65
66 Ok(Ed25519VerificationKey2020 {
67 _type: String::from(SUITE_ID),
68 id,
69 controller,
70 public_key_multibase,
71 private_key_multibase,
72 revoked: false,
73 })
74 }
75
76 fn is_valid_key_header(multibase_key: &String, expected_header: &[u8; 2]) -> bool {
77 if !multibase_key[0..1].eq(MULTIBASE_BASE58BTC_HEADER) {
78 return false;
79 }
80
81 let decoded = multibase::decode(&multibase_key);
82 let (_, decoded_key_bytes) = match decoded {
83 Ok(val) => val,
84 Err(_error) => return false,
85 };
86
87 decoded_key_bytes[0] == expected_header[0] && decoded_key_bytes[1] == expected_header[1]
88 }
89}
90
91impl VerificationKey for Ed25519VerificationKey2020 {
92 fn from_fingerprint(fingerprint: &str) -> Result<Self, Error> {
93 Ed25519VerificationKey2020::new(
94 None,
95 String::from(fingerprint),
96 None,
97 Some(String::from(fingerprint)),
98 )
99 }
100
101 fn get_suite_id() -> &'static str
102 where
103 Self: Sized,
104 {
105 SUITE_ID
106 }
107
108 fn get_suite_context() -> &'static str
109 where
110 Self: Sized,
111 {
112 SUITE_CONTEXT
113 }
114 fn get_private_key_content(&self) -> &Option<String> {
115 &self.private_key_multibase
116 }
117 fn get_public_key_content(&self) -> &String {
118 &self.public_key_multibase
119 }
120
121 fn get_current_suite_id(&self) -> &'static str
122 where
123 Self: Sized,
124 {
125 SUITE_ID
126 }
127
128 fn get_current_suite_context(&self) -> &'static str
129 where
130 Self: Sized,
131 {
132 SUITE_CONTEXT
133 }
134
135 fn get_controller(&self) -> &Option<String> {
136 &self.controller
137 }
138 fn export(&self, public_key: bool, private_key: bool, include_context: bool) -> KeyPair {
139 KeyPair {
140 id: self.id.clone(),
141 _type: self._type.clone(),
142 context: match include_context {
143 true => Some(String::from(SUITE_CONTEXT)),
144 false => None,
145 },
146 public_key_base58: None,
147 private_key_base58: None,
148 private_key_multibase: match private_key {
149 true => self.private_key_multibase.clone(),
150 false => None,
151 },
152 public_key_multibase: match public_key {
153 true => Some(self.public_key_multibase.clone()),
154 false => None,
155 },
156 revoked: self.revoked,
157 controller: self.controller.clone(),
158 }
159 }
160
161 fn get_type(&self) -> String {
162 self._type.clone()
163 }
164}