1#[cfg(not(feature = "std"))]
3use alloc::vec::Vec;
4#[cfg(feature = "std")]
5use std::vec::Vec;
6
7use crate::{
8 errors::LllvError,
9 header::{CapsuleFlags, CapsuleHeader},
10 version::HEADER_LEN,
11};
12use blake3::hash;
13use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
14
15#[derive(Clone, Debug)]
16pub struct Capsule {
17 pub header: CapsuleHeader,
18 pub payload: Vec<u8>,
19}
20
21impl Capsule {
22 pub fn create(
30 dim: u16,
31 payload: &[u8],
32 flags: CapsuleFlags,
33 sk: &SigningKey,
34 ) -> Result<Self, LllvError> {
35 let cid = *hash(payload).as_bytes();
36 #[cfg(feature = "std")]
37 let ts_ms = u64::try_from(
38 std::time::SystemTime::now()
39 .duration_since(std::time::UNIX_EPOCH)
40 .map_err(|_| LllvError::TimestampOverflow)?
41 .as_millis(),
42 )
43 .map_err(|_| LllvError::TimestampOverflow)?;
44 #[cfg(not(feature = "std"))]
45 let ts_ms = 0u64; let len = u32::try_from(payload.len()).map_err(|_| LllvError::MismatchedLengths)?;
47 let mut header = CapsuleHeader::empty(dim, flags, cid, len, ts_ms);
48
49 let mut to_sign = Vec::with_capacity(HEADER_LEN - 64 + payload.len());
51 to_sign.extend_from_slice(&header.to_bytes_wo_sig());
52 to_sign.extend_from_slice(payload);
53
54 let sig: Signature = sk.sign(&to_sign);
55 header.sig.copy_from_slice(&sig.to_bytes());
56
57 Ok(Self {
58 header,
59 payload: payload.to_vec(),
60 })
61 }
62
63 #[must_use]
64 pub fn to_bytes(&self) -> Vec<u8> {
65 let mut v = Vec::with_capacity(HEADER_LEN + self.payload.len());
66 v.extend_from_slice(&self.header.to_bytes());
67 v.extend_from_slice(&self.payload);
68 v
69 }
70
71 pub fn from_bytes(raw: &[u8]) -> Result<Self, LllvError> {
76 let header = CapsuleHeader::from_bytes(raw)?;
77 let payload = raw[HEADER_LEN..].to_vec();
78 if payload.len() != header.len as usize {
79 return Err(LllvError::MismatchedLengths);
80 }
81 Ok(Self { header, payload })
82 }
83
84 pub fn verify_cid(&self) -> Result<(), LllvError> {
89 let cid_now = *hash(&self.payload).as_bytes();
90 if cid_now != self.header.cid {
91 return Err(LllvError::BadSignature);
92 }
93 Ok(())
94 }
95
96 pub fn verify_with(&self, pk: &VerifyingKey) -> Result<(), LllvError> {
103 self.verify_cid()?;
104 let mut to_verify = Vec::with_capacity(HEADER_LEN - 64 + self.payload.len());
105 to_verify.extend_from_slice(&self.header.to_bytes_wo_sig());
106 to_verify.extend_from_slice(&self.payload);
107
108 let sig = ed25519_dalek::Signature::from_bytes(&self.header.sig);
109 pk.verify_strict(&to_verify, &sig)
110 .map_err(|_| LllvError::BadSignature)
111 }
112
113 #[deprecated(
114 since = "0.1.0",
115 note = "use verify_with(&pk) para autenticidade ou verify_cid() para integridade"
116 )]
117 pub fn verify(&self) -> Result<(), LllvError> {
123 self.verify_cid()
124 }
125}