use base64ct::{Base64UrlUnpadded, Encoding};
use bytes::BytesMut;
use core::fmt;
use std::{
fmt::{Debug, Display},
ops::Deref,
};
use zeroize::Zeroize;
#[cfg(feature = "async")]
use futures::Stream;
#[cfg(feature = "pq")]
use crate::vid::did::web::Algorithm;
use crate::vid::did::web::{Curve, KeyType};
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
pub type Digest = [u8; 32];
#[derive(Clone, Zeroize)]
pub struct PrivateKeyData(Vec<u8>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PublicKeyData(Vec<u8>);
#[derive(Clone, Zeroize)]
pub struct PrivateSigningKeyData(Vec<u8>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PublicVerificationKeyData(Vec<u8>);
pub type VidData<'a> = &'a [u8];
pub type NonConfidentialData<'a> = &'a [u8];
pub type TSPMessage = Vec<u8>;
#[cfg(feature = "async")]
pub type TSPStream<D, E> = std::pin::Pin<Box<dyn Stream<Item = Result<D, E>> + Send>>;
#[derive(Debug)]
pub struct MessageType {
pub crypto_type: crate::cesr::CryptoType,
pub signature_type: crate::cesr::SignatureType,
}
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum RelationshipStatus {
_Controlled,
Bidirectional {
thread_id: Digest,
outstanding_nested_thread_ids: Vec<Digest>,
},
Unidirectional {
thread_id: Digest,
},
ReverseUnidirectional {
thread_id: Digest,
},
Unrelated,
}
impl RelationshipStatus {
pub(crate) fn bi_default() -> Self {
RelationshipStatus::Bidirectional {
thread_id: [0; 32],
outstanding_nested_thread_ids: vec![],
}
}
pub(crate) fn bi(thread_id: Digest) -> Self {
RelationshipStatus::Bidirectional {
thread_id,
outstanding_nested_thread_ids: vec![],
}
}
}
impl Display for RelationshipStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RelationshipStatus::_Controlled => write!(f, "Controlled"),
RelationshipStatus::Bidirectional { .. } => write!(f, "Bidirectional"),
RelationshipStatus::Unidirectional { .. } => write!(f, "Unidirectional"),
RelationshipStatus::ReverseUnidirectional { .. } => write!(f, "ReverseUnidirectional"),
RelationshipStatus::Unrelated => write!(f, "Unrelated"),
}
}
}
#[derive(Debug)]
pub enum ReceivedTspMessage<Data: AsRef<[u8]> = BytesMut> {
GenericMessage {
sender: String,
receiver: Option<String>,
nonconfidential_data: Option<Data>,
message: Data,
message_type: MessageType,
},
RequestRelationship {
sender: String,
receiver: String,
route: Option<Vec<Vec<u8>>>,
nested_vid: Option<String>,
thread_id: Digest,
},
AcceptRelationship {
sender: String,
receiver: String,
nested_vid: Option<String>,
},
CancelRelationship {
sender: String,
receiver: String,
},
ForwardRequest {
sender: String,
receiver: String,
next_hop: String,
route: Vec<BytesMut>,
opaque_payload: BytesMut,
},
NewIdentifier {
sender: String,
receiver: String,
new_vid: String,
},
Referral {
sender: String,
receiver: String,
referred_vid: String,
},
#[cfg(feature = "async")]
PendingMessage {
unknown_vid: String,
payload: BytesMut,
},
}
mod conversions;
#[derive(Debug, PartialEq, Eq)]
pub enum Payload<'a, Bytes: AsRef<[u8]>, MaybeMutBytes: AsRef<[u8]> = Bytes> {
Content(Bytes),
NestedMessage(MaybeMutBytes),
RoutedMessage(Vec<VidData<'a>>, Bytes),
CancelRelationship {
thread_id: Digest,
},
RequestRelationship {
route: Option<Vec<VidData<'a>>>,
thread_id: Digest,
},
AcceptRelationship {
thread_id: Digest,
},
RequestNestedRelationship {
inner: MaybeMutBytes,
thread_id: Digest,
},
AcceptNestedRelationship {
inner: MaybeMutBytes,
thread_id: Digest,
},
NewIdentifier {
thread_id: Digest,
new_vid: VidData<'a>,
},
Referral {
referred_vid: VidData<'a>,
},
}
impl<Bytes: AsRef<[u8]>, MaybeMutBytes: AsRef<[u8]>> Payload<'_, Bytes, MaybeMutBytes> {
pub fn as_bytes(&self) -> &[u8] {
match self {
Payload::Content(bytes) => bytes.as_ref(),
Payload::NestedMessage(bytes) => bytes.as_ref(),
Payload::RoutedMessage(_, bytes) => bytes.as_ref(),
Payload::CancelRelationship { .. } => &[],
Payload::RequestRelationship { .. } => &[],
Payload::AcceptRelationship { .. } => &[],
Payload::RequestNestedRelationship { .. } => &[],
Payload::AcceptNestedRelationship { .. } => &[],
Payload::NewIdentifier { .. } => &[],
Payload::Referral { .. } => &[],
}
}
}
impl<Bytes: AsRef<[u8]>> fmt::Display for Payload<'_, Bytes> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Payload::Content(bytes) => {
write!(f, "Content: {}", String::from_utf8_lossy(bytes.as_ref()))
}
Payload::NestedMessage(bytes) => write!(
f,
"Nested Message: {}",
String::from_utf8_lossy(bytes.as_ref())
),
Payload::RoutedMessage(hops, bytes) => {
write!(
f,
"Routed Message: {}, route: [",
String::from_utf8_lossy(bytes.as_ref())
)?;
for vid in hops {
write!(f, "{:?}", &vid[..])?
}
write!(f, "]")
}
Payload::CancelRelationship { .. } => write!(f, "Cancel Relationship"),
Payload::RequestRelationship { .. } => write!(f, "Request Relationship"),
Payload::AcceptRelationship { .. } => write!(f, "Accept Relationship"),
Payload::RequestNestedRelationship { .. } => write!(f, "Request Nested Relationship"),
Payload::AcceptNestedRelationship { .. } => write!(f, "Accept Nested Relationship"),
Payload::NewIdentifier { .. } => write!(f, "Request Identifier Change"),
Payload::Referral { .. } => write!(f, "Relationship Referral"),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub enum VidEncryptionKeyType {
#[default]
X25519,
#[cfg(feature = "pq")]
X25519Kyber768Draft00,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub enum VidSignatureKeyType {
#[default]
Ed25519,
#[cfg(feature = "pq")]
MlDsa65,
}
pub trait VerifiedVid: Send + Sync {
fn identifier(&self) -> &str;
fn endpoint(&self) -> &url::Url;
fn verifying_key(&self) -> &PublicVerificationKeyData;
fn encryption_key(&self) -> &PublicKeyData;
fn encryption_key_type(&self) -> VidEncryptionKeyType;
fn signature_key_type(&self) -> VidSignatureKeyType;
fn encryption_key_jwk(&self) -> serde_json::Value {
serde_json::json!({
"kty": Into::<KeyType>::into(self.encryption_key_type()),
"crv": Into::<Curve>::into(self.encryption_key_type()),
"use": "enc",
"x": Base64UrlUnpadded::encode_string(self.encryption_key().as_ref()),
})
}
fn signature_key_jwk(&self) -> serde_json::Value {
match self.signature_key_type() {
VidSignatureKeyType::Ed25519 => {
serde_json::json!({
"kty": Into::<KeyType>::into(self.signature_key_type()),
"crv": Into::<Option<Curve>>::into(self.signature_key_type()),
"use": "sig",
"x": Base64UrlUnpadded::encode_string(self.verifying_key().as_ref()),
})
}
#[cfg(feature = "pq")]
VidSignatureKeyType::MlDsa65 => {
serde_json::json!({
"kty": Into::<KeyType>::into(self.signature_key_type()),
"alg": Into::<Option<Algorithm>>::into(self.signature_key_type()),
"use": "sig",
"pub": Base64UrlUnpadded::encode_string(self.verifying_key().as_ref()),
})
}
}
}
}
pub trait PrivateVid: VerifiedVid + Send + Sync {
fn decryption_key(&self) -> &PrivateKeyData;
fn signing_key(&self) -> &PrivateSigningKeyData;
fn private_encryption_key_jwk(&self) -> serde_json::Value {
serde_json::json!({
"kty": Into::<KeyType>::into(self.encryption_key_type()),
"crv": Into::<Curve>::into(self.encryption_key_type()),
"use": "enc",
"x": Base64UrlUnpadded::encode_string(self.encryption_key().as_ref()),
"d": Base64UrlUnpadded::encode_string(self.decryption_key().as_ref()),
})
}
}
impl Debug for PrivateKeyData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PrivateKeyData([redacted])")
}
}
impl AsRef<[u8]> for PrivateKeyData {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for PublicKeyData {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for PrivateSigningKeyData {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for PublicVerificationKeyData {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl From<Vec<u8>> for PrivateSigningKeyData {
fn from(data: Vec<u8>) -> PrivateSigningKeyData {
PrivateSigningKeyData(data)
}
}
impl From<Vec<u8>> for PublicVerificationKeyData {
fn from(data: Vec<u8>) -> PublicVerificationKeyData {
PublicVerificationKeyData(data)
}
}
impl From<Vec<u8>> for PrivateKeyData {
fn from(data: Vec<u8>) -> PrivateKeyData {
PrivateKeyData(data)
}
}
impl From<Vec<u8>> for PublicKeyData {
fn from(data: Vec<u8>) -> PublicKeyData {
PublicKeyData(data)
}
}
impl Deref for PublicKeyData {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Deref for PrivateKeyData {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Deref for PublicVerificationKeyData {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Deref for PrivateSigningKeyData {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}