rings_core/message/protocols/
verify.rs1#![warn(missing_docs)]
2
3use serde::Deserialize;
6use serde::Serialize;
7
8use crate::consts::DEFAULT_TTL_MS;
9use crate::consts::MAX_TTL_MS;
10use crate::consts::TS_OFFSET_TOLERANCE_MS;
11use crate::dht::Did;
12use crate::error::Result;
13use crate::session::Session;
14use crate::session::SessionSk;
15use crate::utils::get_epoch_ms;
16
17#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
20pub struct MessageVerification {
21 pub session: Session,
23 pub ttl_ms: u64,
25 pub ts_ms: u128,
27 pub sig: Vec<u8>,
29}
30
31fn pack_msg(data: &[u8], ts_ms: u128, ttl_ms: u64) -> Vec<u8> {
32 let mut msg = vec![];
33
34 msg.extend_from_slice(&ts_ms.to_be_bytes());
35 msg.extend_from_slice(&ttl_ms.to_be_bytes());
36 msg.extend_from_slice(data);
37
38 msg
39}
40
41impl MessageVerification {
42 pub fn new(data: &[u8], session_sk: &SessionSk) -> Result<Self> {
44 let ts_ms = get_epoch_ms();
45 let ttl_ms = DEFAULT_TTL_MS;
46 let msg = pack_msg(data, ts_ms, ttl_ms);
47 let verification = MessageVerification {
48 session: session_sk.session(),
49 sig: session_sk.sign(&msg)?,
50 ttl_ms,
51 ts_ms,
52 };
53 Ok(verification)
54 }
55
56 pub fn verify(&self, data: &[u8]) -> bool {
58 let msg = pack_msg(data, self.ts_ms, self.ttl_ms);
59
60 self.session
61 .verify(&msg, &self.sig)
62 .map_err(|e| {
63 tracing::warn!("MessageVerification verify failed: {:?}", e);
64 })
65 .is_ok()
66 }
67}
68
69pub trait MessageVerificationExt {
72 fn verification_data(&self) -> Result<Vec<u8>>;
74
75 fn verification(&self) -> &MessageVerification;
77
78 fn is_expired(&self) -> bool {
80 if self.verification().ttl_ms > MAX_TTL_MS {
81 return false;
82 }
83
84 let now = get_epoch_ms();
85
86 if self.verification().ts_ms - TS_OFFSET_TOLERANCE_MS > now {
87 return false;
88 }
89
90 now > self.verification().ts_ms + self.verification().ttl_ms as u128
91 }
92
93 fn verify(&self) -> bool {
95 if self.is_expired() {
96 tracing::warn!("message expired");
97 return false;
98 }
99
100 let Ok(data) = self.verification_data() else {
101 tracing::warn!("MessageVerificationExt verify get verification_data failed");
102 return false;
103 };
104
105 self.verification().verify(&data)
106 }
107
108 fn signer(&self) -> Did {
110 self.verification().session.account_did()
111 }
112}