1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::{IdentityError, IdentityStateConst};
use core::fmt::{Display, Formatter};
use core::str::FromStr;
use ockam_core::compat::string::String;
use ockam_core::vault::{Hasher, KeyId};
use ockam_core::{Error, Result};
use serde::{Deserialize, Serialize};
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Clone, Debug, Hash, Serialize, Deserialize, Default, PartialOrd, Ord)]
pub struct IdentityIdentifier(KeyId);
impl IdentityIdentifier {
pub const PREFIX: &'static str = "P";
pub fn from_key_id(key_id: KeyId) -> Self {
Self(key_id)
}
pub fn key_id(&self) -> &KeyId {
&self.0
}
pub(crate) fn ct_eq(&self, o: &Self) -> subtle::Choice {
use subtle::ConstantTimeEq;
self.0.as_bytes().ct_eq(o.0.as_bytes())
}
}
impl Eq for IdentityIdentifier {}
impl PartialEq for IdentityIdentifier {
fn eq(&self, o: &Self) -> bool {
self.ct_eq(o).into()
}
}
impl Display for IdentityIdentifier {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let str: String = self.clone().into();
write!(f, "{}", &str)
}
}
impl From<IdentityIdentifier> for String {
fn from(id: IdentityIdentifier) -> Self {
format!("{}{}", IdentityIdentifier::PREFIX, &id.0)
}
}
impl TryFrom<&str> for IdentityIdentifier {
type Error = Error;
fn try_from(value: &str) -> Result<Self> {
if let Some(str) = value.strip_prefix(Self::PREFIX) {
Ok(Self::from_key_id(str.into()))
} else {
Err(IdentityError::InvalidIdentityId.into())
}
}
}
impl TryFrom<String> for IdentityIdentifier {
type Error = Error;
fn try_from(value: String) -> Result<Self> {
Self::try_from(value.as_str())
}
}
impl FromStr for IdentityIdentifier {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash)]
pub struct EventIdentifier([u8; 32]);
impl AsRef<[u8]> for EventIdentifier {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl EventIdentifier {
pub async fn initial(hasher: &(impl Hasher + Sync)) -> Self {
let h = match hasher.sha256(IdentityStateConst::NO_EVENT).await {
Ok(hash) => hash,
Err(_) => panic!("failed to hash initial event"),
};
EventIdentifier::from_hash(h)
}
pub fn from_hash(hash: [u8; 32]) -> Self {
Self(hash)
}
pub fn to_string_representation(&self) -> String {
format!("E_ID.{}", hex::encode(&self.0))
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::{thread_rng, RngCore};
impl IdentityIdentifier {
pub fn random() -> IdentityIdentifier {
IdentityIdentifier(format!("{:x}", thread_rng().next_u64()))
}
}
#[test]
fn test_new() {
let _identifier = IdentityIdentifier::from_key_id("test".to_string());
}
#[test]
fn test_into() {
let id1 = IdentityIdentifier::random();
let str: String = id1.clone().into();
assert!(str.starts_with('P'));
let id2: IdentityIdentifier = str.try_into().unwrap();
assert_eq!(id1, id2);
}
}