Skip to main content

hanzo_did/
verification_method.rs

1//! W3C Verification Methods
2//!
3//! Based on: <https://www.w3.org/TR/did-core/>#verification-methods
4
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8/// Verification Method for DIDs
9#[derive(Debug, Clone, Serialize, Deserialize, Default)]
10#[serde(rename_all = "camelCase")]
11pub struct VerificationMethod {
12    /// The verification method ID
13    pub id: String,
14
15    /// The verification method type
16    #[serde(rename = "type")]
17    pub type_: VerificationMethodType,
18
19    /// The controller of this verification method
20    pub controller: String,
21
22    /// Public key in Multibase format (preferred)
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub public_key_multibase: Option<String>,
25
26    /// Public key in JWK format
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub public_key_jwk: Option<serde_json::Value>,
29
30    /// Public key in PEM format
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub public_key_pem: Option<String>,
33
34    /// Blockchain account identifier
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub blockchain_account_id: Option<String>,
37
38    /// Ethereum address (for EcdsaSecp256k1RecoveryMethod2020)
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub ethereum_address: Option<String>,
41}
42
43/// Verification Method Types as per W3C DID specification
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
45pub enum VerificationMethodType {
46    /// Ed25519 signature verification
47    #[default]
48    #[serde(rename = "Ed25519VerificationKey2020")]
49    Ed25519VerificationKey2020,
50
51    /// Ed25519 signature verification (2018 version)
52    #[serde(rename = "Ed25519VerificationKey2018")]
53    Ed25519VerificationKey2018,
54
55    /// X25519 key agreement
56    #[serde(rename = "X25519KeyAgreementKey2020")]
57    X25519KeyAgreementKey2020,
58
59    /// X25519 key agreement (2019 version)
60    #[serde(rename = "X25519KeyAgreementKey2019")]
61    X25519KeyAgreementKey2019,
62
63    /// ECDSA with secp256k1 curve
64    #[serde(rename = "EcdsaSecp256k1VerificationKey2019")]
65    EcdsaSecp256k1VerificationKey2019,
66
67    /// ECDSA with secp256k1 recovery (Ethereum-style)
68    #[serde(rename = "EcdsaSecp256k1RecoveryMethod2020")]
69    EcdsaSecp256k1RecoveryMethod2020,
70
71    /// JSON Web Key 2020
72    #[serde(rename = "JsonWebKey2020")]
73    JsonWebKey2020,
74
75    /// BLS12-381 signature
76    #[serde(rename = "Bls12381G2Key2020")]
77    Bls12381G2Key2020,
78
79    /// GPG verification key
80    #[serde(rename = "GpgVerificationKey2020")]
81    GpgVerificationKey2020,
82
83    /// RSA verification key
84    #[serde(rename = "RsaVerificationKey2018")]
85    RsaVerificationKey2018,
86
87    /// Custom type
88    #[serde(untagged)]
89    Custom(String),
90}
91
92impl fmt::Display for VerificationMethodType {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        match self {
95            Self::Ed25519VerificationKey2020 => write!(f, "Ed25519VerificationKey2020"),
96            Self::Ed25519VerificationKey2018 => write!(f, "Ed25519VerificationKey2018"),
97            Self::X25519KeyAgreementKey2020 => write!(f, "X25519KeyAgreementKey2020"),
98            Self::X25519KeyAgreementKey2019 => write!(f, "X25519KeyAgreementKey2019"),
99            Self::EcdsaSecp256k1VerificationKey2019 => {
100                write!(f, "EcdsaSecp256k1VerificationKey2019")
101            }
102            Self::EcdsaSecp256k1RecoveryMethod2020 => write!(f, "EcdsaSecp256k1RecoveryMethod2020"),
103            Self::JsonWebKey2020 => write!(f, "JsonWebKey2020"),
104            Self::Bls12381G2Key2020 => write!(f, "Bls12381G2Key2020"),
105            Self::GpgVerificationKey2020 => write!(f, "GpgVerificationKey2020"),
106            Self::RsaVerificationKey2018 => write!(f, "RsaVerificationKey2018"),
107            Self::Custom(s) => write!(f, "{s}"),
108        }
109    }
110}
111
112impl VerificationMethod {
113    /// Create a new Ed25519 verification method
114    pub fn new_ed25519(id: String, controller: String, public_key: &[u8; 32]) -> Self {
115        use multibase::Base;
116        let public_key_multibase = multibase::encode(Base::Base58Btc, public_key);
117
118        Self {
119            id,
120            type_: VerificationMethodType::Ed25519VerificationKey2020,
121            controller,
122            public_key_multibase: Some(public_key_multibase),
123            ..Default::default()
124        }
125    }
126
127    /// Create a new X25519 key agreement method
128    pub fn new_x25519(id: String, controller: String, public_key: &[u8; 32]) -> Self {
129        use multibase::Base;
130        let public_key_multibase = multibase::encode(Base::Base58Btc, public_key);
131
132        Self {
133            id,
134            type_: VerificationMethodType::X25519KeyAgreementKey2020,
135            controller,
136            public_key_multibase: Some(public_key_multibase),
137            ..Default::default()
138        }
139    }
140
141    /// Create an Ethereum-style verification method
142    pub fn new_ethereum(id: String, controller: String, ethereum_address: String) -> Self {
143        Self {
144            id,
145            type_: VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020,
146            controller,
147            ethereum_address: Some(ethereum_address),
148            ..Default::default()
149        }
150    }
151
152    /// Check if this is a signing method
153    pub fn is_signing_method(&self) -> bool {
154        matches!(
155            self.type_,
156            VerificationMethodType::Ed25519VerificationKey2020
157                | VerificationMethodType::Ed25519VerificationKey2018
158                | VerificationMethodType::EcdsaSecp256k1VerificationKey2019
159                | VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020
160                | VerificationMethodType::Bls12381G2Key2020
161                | VerificationMethodType::RsaVerificationKey2018
162        )
163    }
164
165    /// Check if this is a key agreement method
166    pub fn is_key_agreement_method(&self) -> bool {
167        matches!(
168            self.type_,
169            VerificationMethodType::X25519KeyAgreementKey2020
170                | VerificationMethodType::X25519KeyAgreementKey2019
171        )
172    }
173}