Skip to content

Commit

Permalink
Sovrin-specific DDO facade (#871)
Browse files Browse the repository at this point in the history
* WIP

* Use extra fields from did_doc_sov in did_resolver_sov

* Change key type

* Remove extra fields on verification method

* Use KeyKind for keys in service

* Use enum for public key field in verification method

* Use enum for verification method types

* Add pubkey dereferencing

* Update did_resolver_sov

* ExtraFields -> ExtraFieldsSov

* Fail early - try converting all services

* Remove From<String> for KeyKind

* Remove Default for KeyKind

* Remove ServicesList

---------

Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
  • Loading branch information
mirgee authored Jun 20, 2023
1 parent 83b1286 commit 4d89351
Show file tree
Hide file tree
Showing 29 changed files with 1,337 additions and 230 deletions.
42 changes: 38 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"aries_vcx_core",
"uniffi_aries_vcx/core",
"did_doc",
"did_doc_sov",
"did_parser",
"did_resolver",
"did_resolver_registry",
Expand Down
4 changes: 4 additions & 0 deletions did_doc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ version = "0.1.0"
edition = "2021"

[dependencies]
base64 = "0.21.2"
bs58 = "0.5.0"
did_parser = { path = "../did_parser" }
hex = "0.4.3"
multibase = "0.9.1"
pem = "2.0.1"
serde = { version = "1.0.159", default-features = false, features = ["derive"] }
serde_json = "1.0.95"
uniresid = { version = "0.1.4", default-features = false, features = ["serde"] }
Expand Down
51 changes: 49 additions & 2 deletions did_doc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ use url::ParseError;
pub enum DidDocumentBuilderError {
InvalidInput(String),
MissingField(&'static str),
UnsupportedPublicKeyField(&'static str),
JsonError(serde_json::Error),
PemError(pem::PemError),
Base58DecodeError(bs58::decode::Error),
Base64DecodeError(base64::DecodeError),
HexDecodeError(hex::FromHexError),
}

impl std::fmt::Display for DidDocumentBuilderError {
Expand All @@ -16,19 +21,37 @@ impl std::fmt::Display for DidDocumentBuilderError {
DidDocumentBuilderError::MissingField(field) => {
write!(f, "Missing field: {}", field)
}
DidDocumentBuilderError::UnsupportedPublicKeyField(field) => {
write!(f, "Unsupported public key field: {}", field)
}
DidDocumentBuilderError::JsonError(error) => {
write!(f, "(De)serialization error: {}", error)
}
DidDocumentBuilderError::PemError(error) => {
write!(f, "PEM error: {}", error)
}
DidDocumentBuilderError::Base58DecodeError(error) => {
write!(f, "Base58 decode error: {}", error)
}
DidDocumentBuilderError::Base64DecodeError(error) => {
write!(f, "Base64 decode error: {}", error)
}
DidDocumentBuilderError::HexDecodeError(error) => {
write!(f, "Hex decode error: {}", error)
}
}
}
}

impl std::error::Error for DidDocumentBuilderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
DidDocumentBuilderError::InvalidInput(_) => None,
DidDocumentBuilderError::MissingField(_) => None,
DidDocumentBuilderError::JsonError(error) => Some(error),
DidDocumentBuilderError::PemError(error) => Some(error),
DidDocumentBuilderError::Base58DecodeError(error) => Some(error),
DidDocumentBuilderError::Base64DecodeError(error) => Some(error),
DidDocumentBuilderError::HexDecodeError(error) => Some(error),
_ => None,
}
}
}
Expand All @@ -39,6 +62,30 @@ impl From<serde_json::Error> for DidDocumentBuilderError {
}
}

impl From<pem::PemError> for DidDocumentBuilderError {
fn from(error: pem::PemError) -> Self {
DidDocumentBuilderError::PemError(error)
}
}

impl From<bs58::decode::Error> for DidDocumentBuilderError {
fn from(error: bs58::decode::Error) -> Self {
DidDocumentBuilderError::Base58DecodeError(error)
}
}

impl From<base64::DecodeError> for DidDocumentBuilderError {
fn from(error: base64::DecodeError) -> Self {
DidDocumentBuilderError::Base64DecodeError(error)
}
}

impl From<hex::FromHexError> for DidDocumentBuilderError {
fn from(error: hex::FromHexError) -> Self {
DidDocumentBuilderError::HexDecodeError(error)
}
}

impl From<ParseError> for DidDocumentBuilderError {
fn from(error: ParseError) -> Self {
DidDocumentBuilderError::InvalidInput(error.to_string())
Expand Down
37 changes: 27 additions & 10 deletions did_doc/src/schema/did_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::{
verification_method::{VerificationMethod, VerificationMethodKind},
};

type ControllerAlias = OneOrList<Did>;
pub type ControllerAlias = OneOrList<Did>;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
#[serde(default)]
Expand Down Expand Up @@ -92,6 +92,13 @@ impl<E> DidDocument<E> {
self.extra.get(key)
}

pub fn dereference_key(&self, reference: &DidUrl) -> Option<&VerificationMethod> {
// TODO: Should check controller (if present)
self.verification_method
.iter()
.find(|vm| vm.id().fragment() == reference.fragment())
}

pub fn validate(&self) -> Result<(), DidDocumentBuilderError> {
Ok(())
}
Expand Down Expand Up @@ -183,7 +190,7 @@ impl<E> DidDocumentBuilder<E> {
self
}

pub fn add_key_agreement_refrence(mut self, reference: DidUrl) -> Self {
pub fn add_key_agreement_reference(mut self, reference: DidUrl) -> Self {
self.key_agreement
.push(VerificationMethodKind::Resolvable(reference));
self
Expand All @@ -195,7 +202,7 @@ impl<E> DidDocumentBuilder<E> {
self
}

pub fn add_capability_invocation_refrence(mut self, reference: DidUrl) -> Self {
pub fn add_capability_invocation_reference(mut self, reference: DidUrl) -> Self {
self.capability_invocation
.push(VerificationMethodKind::Resolvable(reference));
self
Expand Down Expand Up @@ -248,26 +255,29 @@ impl<E> DidDocumentBuilder<E> {
#[cfg(test)]
mod tests {
use super::*;
use crate::schema::service::ServiceBuilder;
use crate::schema::{service::ServiceBuilder, verification_method::VerificationMethodType};

#[test]
fn test_did_document_builder() {
let id = Did::parse("did:example:123456789abcdefghi".to_string()).unwrap();
let also_known_as = Uri::new("https://example.com").unwrap();
let controller = Did::parse("did:example:controller".to_string()).unwrap();

let vm1_id = DidUrl::parse("did:example:vm1#vm1".to_string()).unwrap();
let verification_method = VerificationMethod::builder(
DidUrl::parse("did:example:vm1".to_string()).unwrap(),
Did::parse("did:example:vm2".to_string()).unwrap(),
"typevm".to_string(),
vm1_id.clone(),
Did::parse("did:example:vm1".to_string()).unwrap(),
VerificationMethodType::Ed25519VerificationKey2018,
)
.add_public_key_base58("H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV".to_string())
.build();
let authentication_reference = DidUrl::parse("did:example:authref".to_string()).unwrap();
let assertion_method = VerificationMethod::builder(
DidUrl::parse("did:example:am1".to_string()).unwrap(),
Did::parse("did:example:am2".to_string()).unwrap(),
"typeam".to_string(),
VerificationMethodType::Ed25519VerificationKey2018,
)
.add_public_key_base58("H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV".to_string())
.build();

let service_id = Uri::new("did:example:123456789abcdefghi;service-1").unwrap();
Expand All @@ -291,9 +301,9 @@ mod tests {
.add_assertion_method(assertion_method.clone())
.add_assertion_method_reference(authentication_reference.clone())
.add_key_agreement(verification_method.clone())
.add_key_agreement_refrence(authentication_reference.clone())
.add_key_agreement_reference(authentication_reference.clone())
.add_capability_invocation(verification_method.clone())
.add_capability_invocation_refrence(authentication_reference.clone())
.add_capability_invocation_reference(authentication_reference.clone())
.add_capability_delegation(verification_method.clone())
.add_capability_delegation_refrence(authentication_reference.clone())
.add_service(service.clone())
Expand Down Expand Up @@ -345,5 +355,12 @@ mod tests {
]
);
assert_eq!(document.service(), &[service]);

let vm = document.dereference_key(&vm1_id);
if let Some(vm) = vm {
assert_eq!(vm.id(), &vm1_id);
} else {
panic!("Verification method not found")
};
}
}
2 changes: 1 addition & 1 deletion did_doc/src/schema/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod did_doc;
pub mod service;
pub mod types;
pub(crate) mod utils;
pub mod utils;
pub mod verification_method;
2 changes: 1 addition & 1 deletion did_doc/src/schema/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{
utils::OneOrList,
};

type ServiceTypeAlias = OneOrList<String>;
pub type ServiceTypeAlias = OneOrList<String>;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
Expand Down
4 changes: 4 additions & 0 deletions did_doc/src/schema/types/jsonwebkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ impl JsonWebKey {
pub fn new(jwk: &str) -> Result<Self, DidDocumentBuilderError> {
Ok(serde_json::from_str(jwk)?)
}

pub fn to_vec(&self) -> Result<Vec<u8>, DidDocumentBuilderError> {
serde_json::to_vec(self).map_err(|e| e.into())
}
}

impl FromStr for JsonWebKey {
Expand Down
Loading

0 comments on commit 4d89351

Please sign in to comment.