key_resolver/
x25519_key_agreement_key2019.rs1use bs58::encode;
2use fi_common::error::Error;
3
4use crate::{
5 common::{AgreementKey, KeyPair, VerificationKey},
6 ed25519_verification_key2018::Ed25519VerificationKey2018,
7 util::{
8 ed25519_to_x25519_privkey, ed25519_to_x25519_pubkey, get_key_bytes_from_key_pair_bytes,
9 MULTIBASE_BASE58BTC_HEADER,
10 },
11};
12
13pub const SUITE_ID: &str = "X25519KeyAgreementKey2019";
14
15pub const SUITE_CONTEXT: &str = "https://w3id.org/security/suites/x25519-2019/v1";
16
17pub struct X25519KeyAgreementKey2019 {
18 _type: String,
19 id: Option<String>,
20 controller: Option<String>,
21 public_key_base58: String,
22 private_key_base58: Option<String>,
23 revoked: bool,
24}
25
26impl X25519KeyAgreementKey2019 {
27 pub fn new(
28 controller: Option<String>,
29 public_key_base58: String,
30 private_key_base58: Option<String>,
31 fingerprint: Option<String>,
32 ) -> Self {
33 let mut id: Option<String> = None;
34 if controller.is_some() && fingerprint.is_some() {
35 let ctrler = controller.clone().unwrap();
36 let fprint = fingerprint.clone().unwrap();
37 id = Some(format!("{}#{}", ctrler, fprint));
38 }
39
40 X25519KeyAgreementKey2019 {
41 _type: String::from(SUITE_ID),
42 id,
43 controller,
44 public_key_base58,
45 private_key_base58,
46 revoked: false,
47 }
48 }
49
50 pub fn from_ed25519_verification_key2018(
51 key_pair: &Box<dyn VerificationKey>,
52 ) -> Result<X25519KeyAgreementKey2019, Error> {
53 if !key_pair
54 .get_current_suite_id()
55 .eq(Ed25519VerificationKey2018::get_suite_id())
56 {
57 return Err(Error::new(
58 "'key_pair' is not a Ed25519VerificationKey2018 struct instance",
59 ));
60 }
61
62 let public_key_content = key_pair.get_public_key_content();
63
64 let public_key_base58 = match convert_from_ed_public_key(public_key_content) {
65 Ok(val) => val,
66 Err(error) => return Err(error),
67 };
68
69 let private_key_content_option = key_pair.get_private_key_content();
70
71 let mut private_key_base58: Option<String> = None;
72 if private_key_content_option.is_some() {
73 let private_key_content = private_key_content_option.clone().unwrap();
74
75 if !public_key_content.starts_with(MULTIBASE_BASE58BTC_HEADER) {
76 return Err(Error::new(
77 format!("Expecting 'privateKeyMultibase' value to be multibase base58btc {} encoded (must start with 'z').", private_key_content).as_str(),
78 ));
79 }
80
81 let private_key = match convert_from_ed_private_key(&private_key_content) {
82 Ok(val) => val,
83 Err(error) => return Err(error),
84 };
85
86 private_key_base58 = Some(private_key);
87 }
88
89 Ok(X25519KeyAgreementKey2019::new(
90 key_pair.get_controller().clone(),
91 public_key_base58,
92 private_key_base58,
93 Some(key_pair.get_public_key_content().clone()),
94 ))
95 }
96}
97
98fn convert_from_ed_public_key(public_key_base58: &String) -> Result<String, Error> {
99 let ed_pub_key_bytes_builder = bs58::decode(public_key_base58);
100
101 let mut ed_pub_key_bytes = match ed_pub_key_bytes_builder.into_vec() {
102 Ok(val) => val,
103 Err(error) => return Err(Error::new(error.to_string().as_str())),
104 };
105
106 let ed25519_pub_key: [u8; 32] =
107 match get_key_bytes_from_key_pair_bytes(&mut ed_pub_key_bytes, true) {
108 Ok(val) => val,
109 Err(error) => {
110 return Err(error);
111 }
112 };
113
114 let dh_pub_key_bytes = match ed25519_to_x25519_pubkey(&ed25519_pub_key) {
115 Ok(val) => val,
116 Err(error) => return Err(error),
117 };
118
119 let dh_pub_key_bytes_base58_builder = encode(dh_pub_key_bytes);
120
121 Ok(dh_pub_key_bytes_base58_builder.into_string())
122}
123
124fn convert_from_ed_private_key(private_key_base58: &String) -> Result<String, Error> {
125 let ed_pri_key_bytes_builder = bs58::decode(private_key_base58);
126
127 let mut ed_pri_key_bytes = match ed_pri_key_bytes_builder.into_vec() {
128 Ok(val) => val,
129 Err(error) => return Err(Error::new(error.to_string().as_str())),
130 };
131
132 let ed25519_priv_key: [u8; 32] =
133 match get_key_bytes_from_key_pair_bytes(&mut ed_pri_key_bytes, false) {
134 Ok(val) => val,
135 Err(error) => {
136 return Err(error);
137 }
138 };
139
140 let dh_priv_key_bytes = ed25519_to_x25519_privkey(&ed25519_priv_key);
141
142 let dh_priv_key_bytes_base58_builder = encode(dh_priv_key_bytes);
143
144 Ok(dh_priv_key_bytes_base58_builder.into_string())
145}
146
147impl AgreementKey for X25519KeyAgreementKey2019 {
148 fn export(&self, public_key: bool, private_key: bool, include_context: bool) -> KeyPair {
149 KeyPair {
150 id: self.id.clone(),
151 _type: self._type.clone(),
152 context: match include_context {
153 true => Some(String::from(SUITE_CONTEXT)),
154 false => None,
155 },
156 public_key_base58: match public_key {
157 true => Some(self.public_key_base58.clone()),
158 false => None,
159 },
160 private_key_base58: match private_key {
161 true => self.private_key_base58.clone(),
162 false => None,
163 },
164 private_key_multibase: None,
165 public_key_multibase: None,
166 revoked: self.revoked,
167 controller: self.controller.clone(),
168 }
169 }
170
171 fn get_controller(&self) -> &Option<String> {
172 &self.controller
173 }
174
175 fn get_private_key_content(&self) -> &Option<String> {
176 &self.private_key_base58
177 }
178
179 fn get_public_key_content(&self) -> &String {
180 &self.public_key_base58
181 }
182
183 fn get_suite_context() -> &'static str
184 where
185 Self: Sized,
186 {
187 SUITE_CONTEXT
188 }
189
190 fn get_current_suite_context(&self) -> &'static str
191 where
192 Self: Sized,
193 {
194 SUITE_CONTEXT
195 }
196}