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};
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,
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::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),
"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::Secp256k1 => DIDKey::generate(SecretsKeyType::Secp256k1).map_err(|e| {
TDKError::DIDMethod(format!("Couldn't create Secp256k1 did:key : {}", e))
}),
}
}
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 services = didcomm_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.0, "#key-", (id + 1).to_string().as_str()].concat();
}
Ok((peer.0, secrets))
}
}