From 37a3130474e12427d4f96fdcef315173e8529cdb Mon Sep 17 00:00:00 2001 From: Miroslav Kovar Date: Mon, 21 Aug 2023 19:27:47 +0200 Subject: [PATCH] Expose public key getter on verification method (#941) Signed-off-by: Miroslav Kovar --- Cargo.lock | 1 + did_doc/Cargo.toml | 1 + did_doc/src/error.rs | 17 +++++++ did_doc/src/schema/verification_method/mod.rs | 2 +- .../schema/verification_method/public_key.rs | 2 - .../verification_method.rs | 47 +++++++++++++++++-- .../verification_method_type.rs | 23 ++++++++- .../numalgos/numalgo2/verification_method.rs | 10 ++-- did_resolver_sov/src/resolution/utils.rs | 2 +- 9 files changed, 91 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f02dd8eee..3bdf616747 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1643,6 +1643,7 @@ dependencies = [ "hex", "multibase", "pem 2.0.1", + "public_key", "serde", "serde_json", "uniresid", diff --git a/did_doc/Cargo.toml b/did_doc/Cargo.toml index 38aa946160..106b002025 100644 --- a/did_doc/Cargo.toml +++ b/did_doc/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" base64 = "0.21.2" bs58 = "0.5.0" did_parser = { path = "../did_parser" } +public_key = { path = "../public_key" } hex = "0.4.3" multibase = "0.9.1" pem = "2.0.1" diff --git a/did_doc/src/error.rs b/did_doc/src/error.rs index d1cacb7dd1..16b42c0d4a 100644 --- a/did_doc/src/error.rs +++ b/did_doc/src/error.rs @@ -1,5 +1,7 @@ use url::ParseError; +use crate::schema::verification_method::VerificationMethodType; + #[derive(Debug)] pub enum DidDocumentBuilderError { InvalidInput(String), @@ -10,6 +12,8 @@ pub enum DidDocumentBuilderError { Base58DecodeError(bs58::decode::Error), Base64DecodeError(base64::DecodeError), HexDecodeError(hex::FromHexError), + UnsupportedVerificationMethodType(VerificationMethodType), + PublicKeyError(public_key::PublicKeyError), } impl std::fmt::Display for DidDocumentBuilderError { @@ -39,6 +43,12 @@ impl std::fmt::Display for DidDocumentBuilderError { DidDocumentBuilderError::HexDecodeError(error) => { write!(f, "Hex decode error: {}", error) } + DidDocumentBuilderError::UnsupportedVerificationMethodType(vm_type) => { + write!(f, "Unsupported verification method type: {}", vm_type) + } + DidDocumentBuilderError::PublicKeyError(error) => { + write!(f, "Public key error: {}", error) + } } } } @@ -51,6 +61,7 @@ impl std::error::Error for DidDocumentBuilderError { DidDocumentBuilderError::Base58DecodeError(error) => Some(error), DidDocumentBuilderError::Base64DecodeError(error) => Some(error), DidDocumentBuilderError::HexDecodeError(error) => Some(error), + DidDocumentBuilderError::PublicKeyError(error) => Some(error), _ => None, } } @@ -91,3 +102,9 @@ impl From for DidDocumentBuilderError { DidDocumentBuilderError::InvalidInput(error.to_string()) } } + +impl From for DidDocumentBuilderError { + fn from(error: public_key::PublicKeyError) -> Self { + DidDocumentBuilderError::PublicKeyError(error) + } +} diff --git a/did_doc/src/schema/verification_method/mod.rs b/did_doc/src/schema/verification_method/mod.rs index d4e76e6ce5..fd5cbd21d7 100644 --- a/did_doc/src/schema/verification_method/mod.rs +++ b/did_doc/src/schema/verification_method/mod.rs @@ -3,7 +3,7 @@ mod verification_method; mod verification_method_kind; mod verification_method_type; -pub use public_key::PublicKeyField; +pub use self::public_key::PublicKeyField; pub use verification_method::{ CompleteVerificationMethodBuilder, IncompleteVerificationMethodBuilder, VerificationMethod, }; diff --git a/did_doc/src/schema/verification_method/public_key.rs b/did_doc/src/schema/verification_method/public_key.rs index c392501d44..4a5c078bf4 100644 --- a/did_doc/src/schema/verification_method/public_key.rs +++ b/did_doc/src/schema/verification_method/public_key.rs @@ -58,8 +58,6 @@ impl PublicKeyField { pub fn base58(&self) -> Result { Ok(bs58::encode(self.key_decoded()?).into_string()) } - - // TODO: This should expose a PublicKey getter } #[cfg(test)] diff --git a/did_doc/src/schema/verification_method/verification_method.rs b/did_doc/src/schema/verification_method/verification_method.rs index f97add2799..6c71d1efd6 100644 --- a/did_doc/src/schema/verification_method/verification_method.rs +++ b/did_doc/src/schema/verification_method/verification_method.rs @@ -1,7 +1,8 @@ use did_parser::{Did, DidUrl}; +use public_key::Key; use serde::{Deserialize, Serialize}; -use crate::schema::types::jsonwebkey::JsonWebKey; +use crate::{error::DidDocumentBuilderError, schema::types::jsonwebkey::JsonWebKey}; use super::{public_key::PublicKeyField, VerificationMethodType}; @@ -37,9 +38,16 @@ impl VerificationMethod { &self.verification_method_type } - pub fn public_key(&self) -> &PublicKeyField { + pub fn public_key_field(&self) -> &PublicKeyField { &self.public_key } + + pub fn public_key(&self) -> Result { + Ok(Key::new( + self.public_key.key_decoded()?, + self.verification_method_type.try_into()?, + )?) + } } #[derive(Debug, Clone)] @@ -224,7 +232,7 @@ mod tests { assert_eq!(vm.id(), &id); assert_eq!(vm.controller(), &controller); assert_eq!(vm.verification_method_type(), &verification_method_type); - match vm.public_key() { + match vm.public_key_field() { PublicKeyField::Multibase { public_key_multibase, } => { @@ -252,7 +260,7 @@ mod tests { assert_eq!(vm.id(), &id); assert_eq!(vm.controller(), &controller); assert_eq!(vm.verification_method_type(), &verification_method_type); - match vm.public_key() { + match vm.public_key_field() { PublicKeyField::Multibase { public_key_multibase, } => { @@ -281,4 +289,35 @@ mod tests { ); assert!(vm.is_err()); } + + #[test] + fn test_verification_method_public_key() { + let id = create_valid_did_url(); + let controller = create_valid_did(); + let verification_method_type = create_valid_verification_key_type(); + let public_key_multibase_expected = create_valid_multibase(); + + let vm = VerificationMethod::builder( + id.clone(), + controller.clone(), + verification_method_type.clone(), + ) + .add_public_key_multibase(public_key_multibase_expected.clone()) + .build(); + + match vm.public_key_field() { + PublicKeyField::Multibase { + public_key_multibase, + } => { + assert_eq!( + public_key_multibase.to_string(), + public_key_multibase_expected + ) + } + _ => panic!("Expected public key to be multibase"), + } + + let public_key = vm.public_key().unwrap(); + assert_eq!(public_key.multibase58(), public_key_multibase_expected); + } } diff --git a/did_doc/src/schema/verification_method/verification_method_type.rs b/did_doc/src/schema/verification_method/verification_method_type.rs index 421e1d8e0c..2921fdb40b 100644 --- a/did_doc/src/schema/verification_method/verification_method_type.rs +++ b/did_doc/src/schema/verification_method/verification_method_type.rs @@ -1,8 +1,11 @@ use std::fmt::Display; +use public_key::KeyType; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +use crate::error::DidDocumentBuilderError; + +#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] pub enum VerificationMethodType { JsonWebKey2020, EcdsaSecp256k1VerificationKey2019, @@ -46,3 +49,21 @@ impl Display for VerificationMethodType { } } } + +impl TryFrom for KeyType { + type Error = DidDocumentBuilderError; + + fn try_from(value: VerificationMethodType) -> Result { + match value { + VerificationMethodType::Ed25519VerificationKey2018 + | VerificationMethodType::Ed25519VerificationKey2020 => Ok(KeyType::Ed25519), + VerificationMethodType::Bls12381G1Key2020 => Ok(KeyType::Bls12381g1), + VerificationMethodType::Bls12381G2Key2020 => Ok(KeyType::Bls12381g2), + VerificationMethodType::X25519KeyAgreementKey2019 + | VerificationMethodType::X25519KeyAgreementKey2020 => Ok(KeyType::X25519), + _ => Err(DidDocumentBuilderError::UnsupportedVerificationMethodType( + value, + )), + } + } +} diff --git a/did_peer/src/numalgos/numalgo2/verification_method.rs b/did_peer/src/numalgos/numalgo2/verification_method.rs index 133efff56e..ef6be70bc7 100644 --- a/did_peer/src/numalgos/numalgo2/verification_method.rs +++ b/did_peer/src/numalgos/numalgo2/verification_method.rs @@ -50,7 +50,7 @@ pub fn get_key_by_verification_method(vm: &VerificationMethod) -> Result return Err(DidPeerError::UnsupportedVerificationMethodType(t.to_owned())), }; - Ok(Key::new(vm.public_key().key_decoded()?, key_type)?) + Ok(Key::new(vm.public_key_field().key_decoded()?, key_type)?) } fn build_verification_methods_from_type_and_key( @@ -159,10 +159,10 @@ mod tests { let vms = get_verification_methods_by_key(key, &did(), PublicKeyEncoding::Multibase).unwrap(); assert_eq!(vms.len(), 1); assert_eq!( - vms[0].public_key().key_decoded().unwrap(), + vms[0].public_key_field().key_decoded().unwrap(), key.multicodec_prefixed_key() ); - assert_ne!(vms[0].public_key().key_decoded().unwrap(), key.key()); + assert_ne!(vms[0].public_key_field().key_decoded().unwrap(), key.key()); } // ... and base58 encoded keys are not @@ -170,10 +170,10 @@ mod tests { let vms = get_verification_methods_by_key(key, &did(), PublicKeyEncoding::Base58).unwrap(); assert_eq!(vms.len(), 1); assert_ne!( - vms[0].public_key().key_decoded().unwrap(), + vms[0].public_key_field().key_decoded().unwrap(), key.multicodec_prefixed_key() ); - assert_eq!(vms[0].public_key().key_decoded().unwrap(), key.key()); + assert_eq!(vms[0].public_key_field().key_decoded().unwrap(), key.key()); } #[test] diff --git a/did_resolver_sov/src/resolution/utils.rs b/did_resolver_sov/src/resolution/utils.rs index a38a80f009..95c49b513d 100644 --- a/did_resolver_sov/src/resolution/utils.rs +++ b/did_resolver_sov/src/resolution/utils.rs @@ -203,7 +203,7 @@ mod tests { "application/did+json" ); if let PublicKeyField::Base58 { public_key_base58 } = - ddo.verification_method()[0].public_key() + ddo.verification_method()[0].public_key_field() { assert_eq!( public_key_base58,