Skip to content

Commit

Permalink
Feature/didpeer4 (#1161)
Browse files Browse the repository at this point in the history
Implement did:peer:4 (#1161)

Signed-off-by: Patrik Stas <[email protected]>
  • Loading branch information
Patrik-Stas authored Mar 21, 2024
1 parent 65024eb commit 05c92f2
Show file tree
Hide file tree
Showing 31 changed files with 663 additions and 285 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

11 changes: 11 additions & 0 deletions did_core/did_doc/src/schema/did_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ impl DidDocumentBuilder {
self
}

// This was needed fo peer:did:4 implementation, but it's assymetric with other methods here
// TODO: Find better approach for the builder
pub fn add_verification_method_2(&mut self, verification_method: VerificationMethod) {
self.verification_method.push(verification_method);
}

pub fn add_authentication_method(mut self, method: VerificationMethod) -> Self {
self.authentication
.push(VerificationMethodKind::Resolved(method));
Expand Down Expand Up @@ -207,6 +213,11 @@ impl DidDocumentBuilder {
self
}

pub fn set_service(mut self, service: Vec<Service>) -> Self {
self.service = service;
self
}

pub fn add_extra_field(mut self, key: String, value: Value) -> Self {
self.extra.insert(key, value);
self
Expand Down
14 changes: 8 additions & 6 deletions did_core/did_doc/src/schema/types/multibase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
str::FromStr,
};

use multibase::{decode, Base};
use multibase::decode;
use serde::{Deserialize, Serialize};
use thiserror::Error;

Expand All @@ -28,7 +28,7 @@ impl Display for MultibaseWrapperError {
// https://datatracker.ietf.org/doc/html/draft-multiformats-multibase-07
#[derive(Clone, Debug, PartialEq)]
pub struct Multibase {
base: Base,
base: multibase::Base,
bytes: Vec<u8>,
}

Expand All @@ -41,7 +41,7 @@ impl Multibase {
Ok(Self { base, bytes })
}

pub fn base_to_multibase(base: Base, encoded: &str) -> Self {
pub fn base_to_multibase(base: multibase::Base, encoded: &str) -> Self {
let multibase_encoded = format!("{}{}", base.code(), encoded);
Self {
base,
Expand Down Expand Up @@ -91,6 +91,8 @@ impl AsRef<[u8]> for Multibase {

#[cfg(test)]
mod tests {
use multibase::Base::Base58Btc;

use super::*;

#[test]
Expand All @@ -113,7 +115,7 @@ mod tests {
assert_eq!(
multibase,
Multibase {
base: Base::Base58Btc,
base: Base58Btc,
bytes: decode("zQmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e")
.unwrap()
.1
Expand Down Expand Up @@ -159,13 +161,13 @@ mod tests {
#[test]
fn test_base_to_multibase() {
let multibase = Multibase::base_to_multibase(
Base::Base58Btc,
Base58Btc,
"QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e",
);
assert_eq!(
multibase,
Multibase {
base: Base::Base58Btc,
base: Base58Btc,
bytes: "zQmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e"
.as_bytes()
.to_vec()
Expand Down
12 changes: 12 additions & 0 deletions did_core/did_doc/src/schema/verification_method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ impl IncompleteVerificationMethodBuilder {
}
}

pub fn add_public_key_field(
self,
public_key: PublicKeyField,
) -> CompleteVerificationMethodBuilder {
CompleteVerificationMethodBuilder {
id: self.id,
controller: self.controller,
verification_method_type: self.verification_method_type,
public_key: Some(public_key),
}
}

pub fn add_public_key_multibase(
self,
public_key_multibase: String,
Expand Down
1 change: 1 addition & 0 deletions did_core/did_methods/did_peer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sha256 = "1.1.4"
log = "0.4.16"
url = { version = "2.3.1", features = ["serde"] }
display_as_json = { path = "../../../misc/display_as_json" }
derive_builder = "0.12.0"

[dev-dependencies]
tokio = { version = "1.27.0", default-features = false, features = ["macros", "rt"] }
Expand Down
59 changes: 51 additions & 8 deletions did_core/did_methods/did_peer/examples/demo.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
use std::error::Error;
use std::{collections::HashMap, error::Error};

use did_doc::schema::{
did_doc::DidDocument,
service::{typed::ServiceType, Service},
types::uri::Uri,
utils::OneOrList,
verification_method::{VerificationMethod, VerificationMethodType},
};
use did_parser_nom::{Did, DidUrl};
use did_peer::{
peer_did::{
numalgos::{numalgo2::Numalgo2, numalgo3::Numalgo3},
numalgos::{
numalgo2::Numalgo2,
numalgo3::Numalgo3,
numalgo4::{encoded_document::DidPeer4EncodedDocumentBuilder, Numalgo4},
},
PeerDid,
},
resolver::{options::PublicKeyEncoding, PeerDidResolutionOptions, PeerDidResolver},
Expand All @@ -19,7 +26,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
demo().await
}

async fn demo() -> Result<(), Box<dyn Error>> {
async fn demo_did_peer_2_and_3() -> Result<(), Box<dyn Error>> {
let did_url = DidUrl::parse("did:foo:bar#key-1".into())?;
let did = Did::parse("did:foo:bar".into())?;
let verification_method = VerificationMethod::builder(
Expand All @@ -33,16 +40,16 @@ async fn demo() -> Result<(), Box<dyn Error>> {
let ddo = DidDocument::builder(did)
.add_verification_method(verification_method)
.build();
println!("Did document: \n{}", serde_json::to_string_pretty(&ddo)?);
log::info!("Did document: \n{}", serde_json::to_string_pretty(&ddo)?);

let peer_did_2 = PeerDid::<Numalgo2>::from_did_doc(ddo.clone())?;
println!("as did:peer numalgo(2): {}", peer_did_2);
log::info!("as did:peer numalgo(2): {}", peer_did_2);

let peer_did_3 = PeerDid::<Numalgo3>::from_did_doc(ddo)?;
println!("as did:peer numalgo(3): {}", peer_did_3);
log::info!("as did:peer numalgo(3): {}", peer_did_3);

let peer_did_3_v2 = peer_did_2.to_numalgo3()?;
println!(
log::info!(
"as did:peer numalgo(2) converted to numalgo(3): {}",
peer_did_3_v2
);
Expand All @@ -56,10 +63,46 @@ async fn demo() -> Result<(), Box<dyn Error>> {
)
.await
.unwrap();
println!(
log::info!(
"Decoded did document: \n{}",
serde_json::to_string_pretty(&did_document)?
);
Ok(())
}

async fn demo_did_peer_4() -> Result<(), Box<dyn Error>> {
let service = Service::new(
Uri::new("#service-0").unwrap(),
"https://example.com/endpoint".parse().unwrap(),
OneOrList::One(ServiceType::DIDCommV2),
HashMap::default(),
);
let encoded_document = DidPeer4EncodedDocumentBuilder::default()
.service(vec![service])
.build()
.unwrap();
log::info!(
"Pseudo did document as input for did:peer:4 construction: {}",
serde_json::to_string_pretty(&encoded_document)?
);

let peer_did_4 = PeerDid::<Numalgo4>::new(encoded_document)?;
log::info!("Instance of peer did: {}", peer_did_4);

let did_document = peer_did_4.resolve_did_doc()?;
log::info!(
"Resolved did document: {}",
serde_json::to_string_pretty(&did_document)?
);
Ok(())
}

async fn demo() -> Result<(), Box<dyn Error>> {
let env = env_logger::Env::default().default_filter_or("info");
env_logger::init_from_env(env);

demo_did_peer_2_and_3().await?;
demo_did_peer_4().await?;

Ok(())
}
Expand Down
2 changes: 2 additions & 0 deletions did_core/did_methods/did_peer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub enum DidPeerError {
RegexError(#[from] regex::Error),
#[error("Public key error: {0}")]
PublicKeyError(#[from] public_key::PublicKeyError),
#[error("General error: {0}")]
GeneralError(String),
}

impl From<Infallible> for DidPeerError {
Expand Down
1 change: 1 addition & 0 deletions did_core/did_methods/did_peer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
extern crate derive_builder;
extern crate display_as_json;

pub mod error;
Expand Down
48 changes: 21 additions & 27 deletions did_core/did_methods/did_peer/src/peer_did/generic.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
use std::fmt::Display;

use did_parser_nom::Did;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use super::PeerDid;
use crate::{
error::DidPeerError,
peer_did::{
numalgos::{kind::NumalgoKind, numalgo2::Numalgo2, numalgo3::Numalgo3},
numalgos::{kind::NumalgoKind, numalgo2::Numalgo2, numalgo3::Numalgo3, numalgo4::Numalgo4},
parse::parse_numalgo,
validate::validate,
},
};

#[derive(Clone, Debug, PartialEq)]
pub enum AnyPeerDid {
Numalgo2(PeerDid<Numalgo2>),
Numalgo3(PeerDid<Numalgo3>),
Numalgo4(PeerDid<Numalgo4>),
}

impl AnyPeerDid {
pub fn parse<T>(did: T) -> Result<AnyPeerDid, DidPeerError>
where
T: Display,
Did: TryFrom<T>,
<Did as TryFrom<T>>::Error: Into<DidPeerError>,
{
log::info!("AnyPeerDid >> parsing input {} as peer:did", did);
let did: Did = did.try_into().map_err(Into::into)?;
log::info!("AnyPeerDid >> parsed did {}", did);
let numalgo = parse_numalgo(&did)?;
validate(&did)?;
log::info!("AnyPeerDid >> parsed numalgo {}", numalgo.to_char());
let parsed = match numalgo {
NumalgoKind::MultipleInceptionKeys(numalgo) => {
AnyPeerDid::Numalgo2(PeerDid { did, numalgo })
}
_ => AnyPeerDid::Numalgo3(PeerDid {
NumalgoKind::MultipleInceptionKeys(numalgo2) => AnyPeerDid::Numalgo2(PeerDid {
did,
numalgo: numalgo2,
}),
NumalgoKind::DidShortening(numalgo3) => AnyPeerDid::Numalgo3(PeerDid {
did,
numalgo: Numalgo3,
numalgo: numalgo3,
}),
NumalgoKind::DidPeer4(numalgo4) => AnyPeerDid::Numalgo4(PeerDid {
did,
numalgo: numalgo4,
}),
o => unimplemented!("Parsing numalgo {} is not supported", o.to_char()),
};
Ok(parsed)
}
Expand All @@ -42,6 +53,7 @@ impl AnyPeerDid {
match self {
AnyPeerDid::Numalgo2(peer_did) => NumalgoKind::MultipleInceptionKeys(peer_did.numalgo),
AnyPeerDid::Numalgo3(peer_did) => NumalgoKind::DidShortening(peer_did.numalgo),
AnyPeerDid::Numalgo4(peer_did) => NumalgoKind::DidPeer4(peer_did.numalgo),
}
}
}
Expand All @@ -54,6 +66,7 @@ impl Serialize for AnyPeerDid {
match &self {
AnyPeerDid::Numalgo2(peer_did) => serializer.serialize_str(peer_did.did().did()),
AnyPeerDid::Numalgo3(peer_did) => serializer.serialize_str(peer_did.did().did()),
AnyPeerDid::Numalgo4(peer_did) => serializer.serialize_str(peer_did.did().did()),
}
}
}
Expand All @@ -77,14 +90,9 @@ mod tests {
.VzXwpBnMdCm1cLmKuzgESn29nqnonp1ioqrQMRHNsmjMyppzx8xB2pv7cw8q1PdDacSrdWE3dtB9f7Nxk886mdzNFoPtY\
.SeyJpZCI6IiNzZXJ2aWNlLTAiLCJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCIsInIiOlsiZGlkOmV4YW1wbGU6c29tZW1lZGlhdG9yI3NvbWVrZXkiXSwiYSI6WyJkaWRjb21tL3YyIiwiZGlkY29tbS9haXAyO2Vudj1yZmM1ODciXX0";

const INVALID_PEER_DID_NUMALGO2: &str = "did:peer:2.Qqqq";

const VALID_PEER_DID_NUMALGO3: &str =
"did:peer:3.d8da5079c166b183cf815ee27747f34e116977103d8b23c96dcba9a9d9429688";

const INVALID_PEER_DID_NUMALGO3: &str =
"did:peer:3.d8da5079c166b183cfz15ee27747f34e116977103d8b23c96dcba9a9d9429689";

fn generic_peer_did_numalgo2() -> AnyPeerDid {
AnyPeerDid::Numalgo2(PeerDid {
did: VALID_PEER_DID_NUMALGO2.parse().unwrap(),
Expand Down Expand Up @@ -125,25 +133,11 @@ mod tests {
assert_eq!(deserialized, generic_peer_did_numalgo2());
}

#[test]
fn numalgo2_invalid() {
let deserialized: Result<AnyPeerDid, _> =
serde_json::from_str(&format!("\"{}\"", INVALID_PEER_DID_NUMALGO2));
assert!(deserialized.is_err());
}

#[test]
fn numalgo3() {
let deserialized: AnyPeerDid =
serde_json::from_str(&format!("\"{}\"", VALID_PEER_DID_NUMALGO3)).unwrap();
assert_eq!(deserialized, generic_peer_did_numalgo3());
}

#[test]
fn numalgo3_invalid() {
let deserialized: Result<AnyPeerDid, _> =
serde_json::from_str(&format!("\"{}\"", INVALID_PEER_DID_NUMALGO3));
assert!(deserialized.is_err());
}
}
}
19 changes: 0 additions & 19 deletions did_core/did_methods/did_peer/src/peer_did/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod numalgos;

mod parse;
mod validate;

pub mod generic;

Expand Down Expand Up @@ -156,24 +155,6 @@ mod tests {
};
}

generate_negative_parse_test!(
unsupported_transform_code,
"did:peer:2\
.Ea6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc\
.Va6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V\
.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCIsInIiOlsiZGlkOmV4YW1wbGU6c29tZW1lZGlhdG9yI3NvbWVrZXkiXX0",
DidPeerError::DidValidationError(_)
);

generate_negative_parse_test!(
malformed_base58_encoding_signing,
"did:peer:2\
.Ez6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc\
.Vz6MkqRYqQiSgvZQdnBytw86Qbs0ZWUkGv22od935YF4s8M7V\
.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCIsInIiOlsiZGlkOmV4YW1wbGU6c29tZW1lZGlhdG9yI3NvbWVrZXkiXX0",
DidPeerError::DidValidationError(_)
);

generate_negative_parse_test!(
malformed_base58_encoding_encryption,
"did:peer:2\
Expand Down
Loading

0 comments on commit 05c92f2

Please sign in to comment.