1use crate::tools::time::{DurationMillis, TimeMillis};
34use crate::tools::{hashing, tools};
35use bytes::Buf;
36use ed25519_dalek::pkcs8::{EncodePrivateKey, SecretDocument};
37use serde::{Deserialize, Serialize};
38use serde_with::{hex::Hex, serde_as};
39use std::fmt;
40
41fn from_buf<const N: usize>(buf: &mut impl Buf, field: &str) -> anyhow::Result<[u8; N]> {
42 anyhow::ensure!(buf.remaining() >= N, "Buffer too short for {}: need {}, have {}", field, N, buf.remaining());
43 let mut arr = [0u8; N];
44 buf.copy_to_slice(&mut arr);
45 Ok(arr)
46}
47
48pub const ID_BYTES: usize = 32;
49
50#[serde_as]
64#[derive(Ord, PartialOrd, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
65pub struct Id(#[serde_as(as = "Hex")] pub [u8; ID_BYTES]);
66
67impl Id {
68 pub fn zero() -> Self {
69 let bytes = [0; ID_BYTES];
70 Self(bytes)
71 }
72
73 pub fn is_zero(&self) -> bool {
74 tools::are_all_zeros(&self.0)
75 }
76
77 pub fn random() -> Self {
78 let mut bytes = [0; ID_BYTES];
79 tools::random_fill_bytes(&mut bytes);
80 Self(bytes)
81 }
82
83 pub fn from_hex_str(str: &str) -> anyhow::Result<Self> {
84 tools::from_hex_str::<Self, ID_BYTES>(str, Self)
85 }
86
87 pub fn to_hex_str(&self) -> String {
88 hex::encode(self.0)
89 }
90
91 pub fn as_bytes(&self) -> &[u8; ID_BYTES] {
92 &self.0
93 }
94
95 pub fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
96 let arr: [u8; ID_BYTES] = bytes.try_into().map_err(|_| anyhow::anyhow!("Invalid id length: expected {}, got {}", ID_BYTES, bytes.len()))?;
97 Ok(Self(arr))
98 }
99
100 pub fn from_buf(buf: &mut impl Buf, field: &str) -> anyhow::Result<Self> {
101 Ok(Self(from_buf::<ID_BYTES>(buf, field)?))
102 }
103
104 pub fn from_hash(hash: Hash) -> anyhow::Result<Id> {
105 if hash.len() != 32 {
106 anyhow::bail!("Invalid Hash length: expected 32 bytes, got {} bytes", hash.len());
107 }
108
109 let id = Id(hash.to_bytes());
110 Ok(id)
111 }
112
113 pub fn from_hashtag_str(hashtag_str: &str) -> anyhow::Result<Id> {
114 let lowercase_str = hashtag_str.to_lowercase();
115 let str_stripped = lowercase_str.strip_prefix('#').unwrap_or(&lowercase_str);
116 let hash = hashing::hash(str_stripped.as_bytes());
117 Id::from_hash(hash)
118 }
119}
120
121impl AsRef<[u8]> for Id {
122 fn as_ref(&self) -> &[u8] {
123 &self.0
124 }
125}
126
127impl fmt::Display for Id {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 write!(f, "{}...", hex::encode(&self.0[0..4]))
130 }
131}
132
133impl fmt::Debug for Id {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 fmt::Display::fmt(self, f)
136 }
137}
138
139pub const SALT_BYTES: usize = 8;
140
141#[serde_as]
152#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
153pub struct Salt(#[serde_as(as = "Hex")] pub [u8; SALT_BYTES]);
154
155impl Salt {
156 pub fn zero() -> Self {
157 Self([0; SALT_BYTES])
158 }
159
160 pub fn random() -> Self {
161 let mut bytes = [0; SALT_BYTES];
162 tools::random_fill_bytes(&mut bytes);
163 Self(bytes)
164 }
165
166 pub fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
167 let arr: [u8; SALT_BYTES] = bytes.try_into().map_err(|_| anyhow::anyhow!("Invalid salt length: expected {}, got {}", SALT_BYTES, bytes.len()))?;
168 Ok(Self(arr))
169 }
170
171 pub fn from_buf(buf: &mut impl Buf, field: &str) -> anyhow::Result<Self> {
172 Ok(Self(from_buf::<SALT_BYTES>(buf, field)?))
173 }
174
175 pub fn randomize(&mut self) {
176 tools::random_fill_bytes(&mut self.0);
177 }
178}
179
180impl AsRef<[u8]> for Salt {
181 fn as_ref(&self) -> &[u8] {
182 &self.0
183 }
184}
185
186impl std::ops::Deref for Salt {
187 type Target = [u8; SALT_BYTES];
188
189 fn deref(&self) -> &Self::Target {
190 &self.0
191 }
192}
193
194impl fmt::Display for Salt {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 let all_zero = self.0.iter().all(|&b| b == 0);
197 match all_zero {
198 true => write!(f, "0"),
199 false => write!(f, "..."),
200 }
201 }
202}
203
204impl fmt::Debug for Salt {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 fmt::Display::fmt(self, f)
207 }
208}
209
210pub const SIGNATURE_BYTES: usize = 64;
211
212#[serde_as]
222#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
223pub struct Signature(#[serde_as(as = "Hex")] pub [u8; SIGNATURE_BYTES]);
224
225impl Signature {
226 pub fn as_bytes(&self) -> &[u8; SIGNATURE_BYTES] {
227 &self.0
228 }
229
230 pub fn from_bytes_exact(bytes: [u8; SIGNATURE_BYTES]) -> Self {
231 Self(bytes)
232 }
233
234 pub fn from_hex_str(str: &str) -> anyhow::Result<Self> {
235 tools::from_hex_str::<Self, SIGNATURE_BYTES>(str, Self)
236 }
237
238 pub fn to_hex_str(&self) -> String {
239 hex::encode(self.0)
240 }
241
242
243 pub fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
244 let arr: [u8; SIGNATURE_BYTES] = bytes.try_into().map_err(|_| anyhow::anyhow!("Invalid signature length: expected {}, got {}", SIGNATURE_BYTES, bytes.len()))?;
245 Ok(Self(arr))
246 }
247
248 pub fn zero() -> Self {
249 Self([0; SIGNATURE_BYTES])
250 }
251
252 pub fn random() -> Self {
253 let mut bytes = [0; SIGNATURE_BYTES];
254 tools::random_fill_bytes(&mut bytes);
255 Self(bytes)
256 }
257
258}
259
260impl fmt::Display for Signature {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 write!(f, "{}...", hex::encode(&self.0[0..4]))
263 }
264}
265
266impl fmt::Debug for Signature {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 fmt::Display::fmt(self, f)
269 }
270}
271
272impl std::ops::Deref for Signature {
273 type Target = [u8; SIGNATURE_BYTES];
274
275 fn deref(&self) -> &Self::Target {
276 &self.0
277 }
278}
279
280impl From<[u8; SIGNATURE_BYTES]> for Signature {
282 fn from(bytes: [u8; SIGNATURE_BYTES]) -> Self {
283 Self(bytes)
284 }
285}
286
287impl From<Signature> for [u8; SIGNATURE_BYTES] {
288 fn from(sig: Signature) -> Self {
289 sig.0
290 }
291}
292
293#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
301pub struct SignatureKey(pub ed25519_dalek::SigningKey);
302
303impl SignatureKey {
304 pub fn from_bytes(bytes: &[u8; SIGNATURE_KEY_BYTES]) -> anyhow::Result<Self> {
305 Ok(Self(ed25519_dalek::SigningKey::from_bytes(bytes)))
306 }
307
308 pub fn verification_key(&self) -> VerificationKey {
309 VerificationKey(self.0.verifying_key())
310 }
311
312 pub fn to_pkcs8_der(&self) -> anyhow::Result<SecretDocument> {
313 Ok(self.0.to_pkcs8_der()?)
314 }
315}
316
317impl AsRef<[u8]> for SignatureKey {
318 fn as_ref(&self) -> &[u8] {
319 self.0.as_bytes()
320 }
321}
322
323#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
324pub struct VerificationKey(pub ed25519_dalek::VerifyingKey);
325
326impl VerificationKey {
327 pub fn from_bytes_raw(bytes: &[u8; VERIFICATION_KEY_BYTES]) -> anyhow::Result<Self> {
328 Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(bytes)?))
329 }
330
331 pub fn from_bytes(bytes: &VerificationKeyBytes) -> anyhow::Result<Self> {
332 Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(&bytes.0)?))
333 }
334
335 pub fn to_verification_key_bytes(&self) -> VerificationKeyBytes {
336 VerificationKeyBytes(self.0.to_bytes())
337 }
338
339 pub fn to_hex(&self) -> String {
340 let vkb = self.to_verification_key_bytes();
341 hex::encode(vkb)
342 }
343
344 pub fn from_hex(hex_str: &str) -> anyhow::Result<Self> {
345 let bytes = hex::decode(hex_str)?;
346 if bytes.len() != VERIFICATION_KEY_BYTES {
347 anyhow::bail!("Invalid hex string length for VerificationKeyBytes");
348 }
349
350 Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(<&[u8; 32]>::try_from(bytes.as_slice())?)?))
351 }
352}
353
354impl AsRef<[u8]> for VerificationKey {
355 fn as_ref(&self) -> &[u8] {
356 self.0.as_bytes()
357 }
358}
359
360
361pub const SIGNATURE_KEY_BYTES: usize = 32;
362#[serde_as]
363#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
364pub struct SignatureKeyBytes(#[serde_as(as = "Hex")] pub [u8; SIGNATURE_KEY_BYTES]);
365
366pub const VERIFICATION_KEY_BYTES: usize = 32;
367
368#[serde_as]
369#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)]
370pub struct VerificationKeyBytes(#[serde_as(as = "Hex")] pub [u8; VERIFICATION_KEY_BYTES]);
371
372impl VerificationKeyBytes {
373 pub fn zero() -> Self {
374 Self([0; VERIFICATION_KEY_BYTES])
375 }
376 pub fn to_verification_key(&self) -> anyhow::Result<VerificationKey> {
377 Ok(VerificationKey(ed25519_dalek::VerifyingKey::from_bytes(&self.0).map_err(|_| anyhow::anyhow!("invalid verification key bytes"))?))
378 }
379 pub fn to_hex(&self) -> String {
380 hex::encode(self.0)
381 }
382 pub fn from_hex_str(str: &str) -> anyhow::Result<Self> {
383 tools::from_hex_str::<Self, VERIFICATION_KEY_BYTES>(str, Self)
384 }
385}
386
387impl AsRef<[u8]> for VerificationKeyBytes {
388 fn as_ref(&self) -> &[u8] {
389 &self.0
390 }
391}
392
393pub const PQ_COMMITMENT_BYTES: usize = 32;
394#[serde_as]
395#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)]
396pub struct PQCommitmentBytes(#[serde_as(as = "Hex")] pub [u8; PQ_COMMITMENT_BYTES]);
397
398impl PQCommitmentBytes {
399
400 pub fn to_hex(&self) -> String {
401 hex::encode(self.0)
402 }
403
404 pub fn from_hex_str(str: &str) -> anyhow::Result<Self> {
405 tools::from_hex_str::<Self, PQ_COMMITMENT_BYTES>(str, Self)
406 }
407
408
409 pub fn zero() -> Self {
410 Self([0; PQ_COMMITMENT_BYTES])
411 }
412
413 pub fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
414 let arr: [u8; PQ_COMMITMENT_BYTES] = bytes.try_into().map_err(|_| anyhow::anyhow!("Invalid PQCommitmentBytes length: expected {}, got {}", PQ_COMMITMENT_BYTES, bytes.len()))?;
415 Ok(Self(arr))
416 }
417}
418
419impl AsRef<[u8]> for PQCommitmentBytes {
420 fn as_ref(&self) -> &[u8] {
421 &self.0
422 }
423}
424
425
426impl PQCommitmentBytes {
427 pub fn from(pq_commitment_falcon: [u8; 16], pq_commitment_dilithium: [u8; 16]) -> Self {
428 let mut combined = [0u8; 32];
429 combined[..16].copy_from_slice(&pq_commitment_falcon);
430 combined[16..].copy_from_slice(&pq_commitment_dilithium);
431 PQCommitmentBytes(combined)
432 }
433}
434
435pub const HASH_BYTES: usize = 32;
436
437#[serde_as]
449#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
450pub struct Hash(#[serde_as(as = "Hex")] pub [u8; HASH_BYTES]);
451
452impl Hash {
453 pub fn zero() -> Self {
454 Self([0; HASH_BYTES])
455 }
456
457 pub fn random() -> Self {
458 let mut bytes = [0; HASH_BYTES];
459 tools::random_fill_bytes(&mut bytes);
460 Self(bytes)
461 }
462
463 pub fn to_bytes(&self) -> [u8; HASH_BYTES] {
464 self.0
465 }
466
467 pub fn as_bytes(&self) -> &[u8; HASH_BYTES] {
468 &self.0
469 }
470
471 pub fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
472 if bytes.len() != HASH_BYTES {
473 anyhow::bail!("incorrect byte count: expected {}, got {}", HASH_BYTES, bytes.len())
474 }
475
476 let mut arr = [0u8; HASH_BYTES];
477 arr.copy_from_slice(bytes);
478 Ok(Self(arr))
479 }
480
481 pub fn randomize(&mut self) {
482 tools::random_fill_bytes(&mut self.0);
483 }
484}
485
486impl AsRef<[u8]> for Hash {
487 fn as_ref(&self) -> &[u8] {
488 &self.0
489 }
490}
491
492impl std::ops::Deref for Hash {
493 type Target = [u8; HASH_BYTES];
494
495 fn deref(&self) -> &Self::Target {
496 &self.0
497 }
498}
499
500impl fmt::Display for Hash {
501 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502 let all_zero = self.0.iter().all(|&b| b == 0);
503 match all_zero {
504 true => write!(f, "0"),
505 false => write!(f, "..."),
506 }
507 }
508}
509
510impl fmt::Debug for Hash {
511 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
512 fmt::Display::fmt(self, f)
513 }
514}
515
516impl From<[u8; HASH_BYTES]> for Hash {
517 fn from(bytes: [u8; HASH_BYTES]) -> Hash {
518 Hash(bytes)
519 }
520}
521
522impl From<&[u8; HASH_BYTES]> for Hash {
523 fn from(bytes: &[u8; HASH_BYTES]) -> Hash {
524 Hash(*bytes)
525 }
526}
527
528#[derive(Debug, PartialEq, Clone)]
529pub struct BucketKey {
530 pub base_id: Id,
531 pub timestamp: TimeMillis,
532 pub granularity: DurationMillis,
533 pub location_id: Id,
534}
535
536#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
546#[serde(transparent)]
547pub struct Pow(pub u8);
548
549impl Pow {
550 pub const fn new(val: u8) -> Self {
551 Self(val)
552 }
553
554 pub fn as_u8(self) -> u8 {
555 self.0
556 }
557}
558
559impl std::fmt::Display for Pow {
560 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
561 write!(f, "{}", self.0)
562 }
563}
564
565impl From<u8> for Pow {
566 fn from(val: u8) -> Self {
567 Self(val)
568 }
569}
570
571impl From<Pow> for u8 {
572 fn from(pow: Pow) -> u8 {
573 pow.0
574 }
575}
576
577#[cfg(test)]
578mod tests {
579 use crate::tools::keys::Keys;
580 use crate::tools::types::{Id, Salt, VerificationKey};
581
582 #[tokio::test]
583 async fn salt_display_zero_test() {
584 let salt = Salt::zero();
585 assert_eq!(format!("{}", salt), "0");
586 }
587
588 #[tokio::test]
589 async fn salt_display_nonzero_test() {
590 let salt = Salt::random();
591 assert_eq!(format!("{}", salt), "...");
592 }
593
594 #[tokio::test]
595 async fn test_hash_to_base_id() -> anyhow::Result<()> {
596 let hash = "walking";
597 let hash1 = "#walking";
598 let hash2 = "WaLkINg";
599 let hash3 = "#WAlkING";
600 let hash4 = "TALKING";
601
602 let id = Id::from_hashtag_str(hash)?;
603 let id1 = Id::from_hashtag_str(hash1)?;
604 let id2 = Id::from_hashtag_str(hash2)?;
605 let id3 = Id::from_hashtag_str(hash3)?;
606 let id4 = Id::from_hashtag_str(hash4)?;
607
608 assert_eq!(id, id1, "Hash to id should be the same");
609 assert_eq!(id, id2, "Hash to id should be the same");
610 assert_eq!(id, id3, "Hash to id should be the same");
611 assert_ne!(id, id4, "Hash to id should not be the same");
612 Ok(())
613 }
614
615 #[tokio::test]
616 async fn test_id_to_str_reversible() -> anyhow::Result<()> {
617 let id = Id::random();
618 let id_str = id.to_hex_str();
619 let id_from_str = Id::from_hex_str(&id_str)?;
620 assert_eq!(id, id_from_str, "Id to string and string to id should be reversible");
621 Ok(())
622 }
623
624 #[tokio::test]
625 async fn test_verification_key() -> anyhow::Result<()> {
626 let keys = Keys::from_phrase("this is a test")?;
627 let hex = keys.verification_key.to_hex();
628 let vfk = VerificationKey::from_hex(&hex)?;
629 assert_eq!(keys.verification_key, vfk, "Verification key to hex and hex to verification key should be reversible");
630 Ok(())
631 }
632}