identity_verification/verification_method/
material.rs1use crate::jose::jwk::Jwk;
5use core::fmt::Debug;
6use core::fmt::Formatter;
7use identity_core::convert::BaseEncoding;
8use serde::de::Visitor;
9use serde::ser::SerializeMap;
10use serde::Deserialize;
11use serde::Serialize;
12use serde::Serializer;
13use serde_json::Value;
14
15use crate::error::Error;
16use crate::error::Result;
17
18#[allow(clippy::large_enum_variant)]
20#[derive(Clone, PartialEq, Eq, Deserialize, Serialize)]
21#[serde(rename_all = "camelCase")]
22#[non_exhaustive]
23pub enum MethodData {
24 PublicKeyMultibase(String),
26 PublicKeyBase58(String),
28 PublicKeyJwk(Jwk),
30 #[serde(untagged)]
32 Custom(CustomMethodData),
33}
34
35impl MethodData {
36 pub fn new_base58(data: impl AsRef<[u8]>) -> Self {
38 Self::PublicKeyBase58(BaseEncoding::encode_base58(&data))
39 }
40
41 pub fn new_multibase(data: impl AsRef<[u8]>) -> Self {
45 Self::PublicKeyMultibase(BaseEncoding::encode_multibase(&data, None))
46 }
47
48 pub fn new_custom(data: impl Into<CustomMethodData>) -> Self {
50 Self::Custom(data.into())
51 }
52
53 pub fn try_decode(&self) -> Result<Vec<u8>> {
61 match self {
62 Self::PublicKeyJwk(_) | Self::Custom(_) => Err(Error::InvalidMethodDataTransformation(
63 "method data is not base encoded",
64 )),
65 Self::PublicKeyMultibase(input) => {
66 BaseEncoding::decode_multibase(input).map_err(|_| Error::InvalidKeyDataMultibase)
67 }
68 Self::PublicKeyBase58(input) => BaseEncoding::decode_base58(input).map_err(|_| Error::InvalidKeyDataBase58),
69 }
70 }
71
72 pub fn public_key_jwk(&self) -> Option<&Jwk> {
74 if let Self::PublicKeyJwk(ref jwk) = self {
75 Some(jwk)
76 } else {
77 None
78 }
79 }
80
81 pub fn try_public_key_jwk(&self) -> Result<&Jwk> {
83 self.public_key_jwk().ok_or(Error::NotPublicKeyJwk)
84 }
85
86 pub fn custom(&self) -> Option<&CustomMethodData> {
88 if let Self::Custom(method_data) = self {
89 Some(method_data)
90 } else {
91 None
92 }
93 }
94}
95
96impl Debug for MethodData {
97 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
98 match self {
99 Self::PublicKeyJwk(inner) => f.write_fmt(format_args!("PublicKeyJwk({inner:#?})")),
100 Self::PublicKeyMultibase(inner) => f.write_fmt(format_args!("PublicKeyMultibase({inner})")),
101 Self::PublicKeyBase58(inner) => f.write_fmt(format_args!("PublicKeyBase58({inner})")),
102 Self::Custom(CustomMethodData { name, data }) => f.write_fmt(format_args!("{name}({data})")),
103 }
104 }
105}
106
107#[derive(Clone, Debug, PartialEq, Eq)]
108pub struct CustomMethodData {
110 pub name: String,
112 pub data: Value,
114}
115
116impl Serialize for CustomMethodData {
117 fn serialize<S>(&self, serializer: S) -> std::prelude::v1::Result<S::Ok, S::Error>
118 where
119 S: Serializer,
120 {
121 let mut map = serializer.serialize_map(Some(1))?;
122 map.serialize_entry(&self.name, &self.data)?;
123 map.end()
124 }
125}
126
127impl<'de> Deserialize<'de> for CustomMethodData {
128 fn deserialize<D>(deserializer: D) -> std::prelude::v1::Result<Self, D::Error>
129 where
130 D: serde::Deserializer<'de>,
131 {
132 deserializer.deserialize_map(CustomMethodDataVisitor)
133 }
134}
135
136struct CustomMethodDataVisitor;
137
138impl<'de> Visitor<'de> for CustomMethodDataVisitor {
139 type Value = CustomMethodData;
140 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 formatter.write_str("\"<any property name>\": <any json value>")
142 }
143 fn visit_map<A>(self, mut map: A) -> std::prelude::v1::Result<Self::Value, A::Error>
144 where
145 A: serde::de::MapAccess<'de>,
146 {
147 let mut custom_method_data = CustomMethodData {
148 name: String::default(),
149 data: Value::Null,
150 };
151 while let Some((name, data)) = map.next_entry::<String, Value>()? {
152 custom_method_data = CustomMethodData { name, data };
153 }
154
155 Ok(custom_method_data)
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162 use serde_json::json;
163
164 #[test]
165 fn serialize_custom_method_data() {
166 let custom = MethodData::Custom(CustomMethodData {
167 name: "anArbitraryMethod".to_owned(),
168 data: json!({"a": 1, "b": 2}),
169 });
170 let target_str = json!({
171 "anArbitraryMethod": {"a": 1, "b": 2},
172 })
173 .to_string();
174 assert_eq!(serde_json::to_string(&custom).unwrap(), target_str);
175 }
176 #[test]
177 fn deserialize_custom_method_data() {
178 let inner_data = json!({
179 "firstCustomField": "a random string",
180 "secondCustomField": 420,
181 });
182 let json_method_data = json!({
183 "myCustomVerificationMethod": &inner_data,
184 });
185 let custom = serde_json::from_value::<MethodData>(json_method_data.clone()).unwrap();
186 let target_method_data = MethodData::Custom(CustomMethodData {
187 name: "myCustomVerificationMethod".to_owned(),
188 data: inner_data,
189 });
190 assert_eq!(custom, target_method_data);
191 }
192}