#[cfg(feature = "did-peer")]
use affinidi_did_common::one_or_many::OneOrMany;
use affinidi_did_key::DIDKey;
use affinidi_secrets_resolver::secrets::{KeyType as SecretsKeyType, Secret};
use affinidi_tdk_common::errors::{Result, TDKError};
#[cfg(feature = "did-peer")]
use did_peer::{
DIDPeer, DIDPeerCreateKeys, DIDPeerKeys, DIDPeerService, PeerServiceEndPoint,
PeerServiceEndPointLong, PeerServiceEndPointLongMap,
};
use std::fmt::Display;
pub enum DIDMethod {
Key,
Peer,
Web,
}
#[derive(Debug)]
pub enum KeyType {
P256,
P384,
Ed25519,
X25519,
Secp256k1,
}
impl Display for KeyType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KeyType::P256 => write!(f, "P-256"),
KeyType::P384 => write!(f, "P-384"),
KeyType::Ed25519 => write!(f, "Ed25519"),
KeyType::X25519 => write!(f, "X25519"),
KeyType::Secp256k1 => write!(f, "secp256k1"),
}
}
}
impl TryFrom<&str> for KeyType {
type Error = String;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
"p-256" => Ok(KeyType::P256),
"p-384" => Ok(KeyType::P384),
"ed25519" => Ok(KeyType::Ed25519),
"x25519" => Ok(KeyType::X25519),
"secp256k1" => Ok(KeyType::Secp256k1),
_ => Err(format!("Unsupported key type: {value}")),
}
}
}
pub struct DID;
impl DID {
pub fn generate_did_key(key_type: KeyType) -> Result<(String, Secret)> {
match key_type {
KeyType::P256 => DIDKey::generate(SecretsKeyType::P256)
.map_err(|e| TDKError::DIDMethod(format!("Couldn't create P256 did:key : {e}"))),
KeyType::P384 => DIDKey::generate(SecretsKeyType::P384)
.map_err(|e| TDKError::DIDMethod(format!("Couldn't create P384 did:key : {e}"))),
KeyType::Ed25519 => DIDKey::generate(SecretsKeyType::Ed25519).map_err(|e| {
TDKError::DIDMethod(format!("Couldn't create Ed25519 did:key : {e}"))
}),
KeyType::X25519 => DIDKey::generate(SecretsKeyType::X25519)
.map_err(|e| TDKError::DIDMethod(format!("Couldn't create X25519 did:key : {e}"))),
KeyType::Secp256k1 => DIDKey::generate(SecretsKeyType::Secp256k1).map_err(|e| {
TDKError::DIDMethod(format!("Couldn't create Secp256k1 did:key : {e}"))
}),
}
}
#[cfg(feature = "did-peer")]
pub fn generate_did_peer_from_secrets(
keys: &mut [(DIDPeerKeys, &mut Secret)],
didcomm_service_uri: Option<String>,
) -> Result<String> {
let mut peer_keys: Vec<DIDPeerCreateKeys> = Vec::new();
let mut secrets: Vec<&mut Secret> = Vec::new();
for (key_type, secret) in keys {
peer_keys.push(DIDPeerCreateKeys {
purpose: key_type.clone(),
type_: None,
public_key_multibase: Some(secret.get_public_keymultibase()?),
});
secrets.push(secret);
}
Self::complete_did_peer_creation(&mut secrets, &peer_keys, didcomm_service_uri)
}
pub fn generate_did_peer(
keys: Vec<(DIDPeerKeys, KeyType)>,
didcomm_service_uri: Option<String>,
) -> Result<(String, Vec<Secret>)> {
let mut peer_keys: Vec<DIDPeerCreateKeys> = Vec::new();
let mut secrets: Vec<Secret> = Vec::new();
for key in keys {
let (did, secret) = Self::generate_did_key(key.1)?;
peer_keys.push(DIDPeerCreateKeys {
purpose: key.0,
type_: None,
public_key_multibase: Some(did[8..].to_string()),
});
secrets.push(secret);
}
let mut secrets_mut: Vec<&mut Secret> = Vec::new();
for secret in secrets.iter_mut() {
secrets_mut.push(secret);
}
let peer =
Self::complete_did_peer_creation(&mut secrets_mut, &peer_keys, didcomm_service_uri)?;
Ok((peer, secrets))
}
#[cfg(feature = "did-peer")]
fn complete_did_peer_creation(
secrets: &mut [&mut Secret],
peer_keys: &Vec<DIDPeerCreateKeys>,
service_uri: Option<String>,
) -> Result<String> {
let services = service_uri.map(|service_uri| {
vec![DIDPeerService {
_type: "dm".into(),
service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
OneOrMany::One(PeerServiceEndPointLongMap {
uri: service_uri,
accept: vec!["didcomm/v2".into()],
routing_keys: vec![],
}),
)),
id: None,
}]
});
let (peer, _) = DIDPeer::create_peer_did(peer_keys, services.as_ref())?;
for (id, secret) in secrets.iter_mut().enumerate() {
secret.id = [&peer, "#key-", (id + 1).to_string().as_str()].concat();
}
Ok(peer)
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "did-peer")]
#[test]
fn did_peer_from_existing_secrets() {
use affinidi_secrets_resolver::secrets::Secret;
use did_peer::DIDPeerKeys;
use crate::dids::DID;
let mut v_secret = Secret::generate_ed25519(None, None);
let mut e_secret =
Secret::generate_x25519(None, None).expect("Couldn't create X25519 Secret");
let mut keys = vec![
(DIDPeerKeys::Verification, &mut v_secret),
(DIDPeerKeys::Encryption, &mut e_secret),
];
let peer =
DID::generate_did_peer_from_secrets(&mut keys, None).expect("Creating DID failed!");
assert_eq!(
peer,
[
"did:peer:2.V",
&keys[0].1.get_public_keymultibase().unwrap(),
".E",
&keys[1].1.get_public_keymultibase().unwrap()
]
.concat()
);
assert_eq!(keys[0].1.id, [&peer, "#key-1"].concat());
assert_eq!(keys[1].1.id, [&peer, "#key-2"].concat());
}
#[cfg(feature = "did-peer")]
#[test]
fn did_peer_create() {
use did_peer::DIDPeerKeys;
use crate::dids::{DID, KeyType};
let keys = vec![
(DIDPeerKeys::Verification, KeyType::Ed25519),
(DIDPeerKeys::Encryption, KeyType::X25519),
];
let (peer, secrets) = DID::generate_did_peer(keys, None).expect("Creating DID failed!");
assert_eq!(
peer,
[
"did:peer:2.V",
&secrets[0].get_public_keymultibase().unwrap(),
".E",
&secrets[1].get_public_keymultibase().unwrap()
]
.concat()
);
assert_eq!(secrets[0].id, [&peer, "#key-1"].concat());
assert_eq!(secrets[1].id, [&peer, "#key-2"].concat());
}
}