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