Skip to main content

px_native/cipher/
sensor.rs

1//! `vP` — top-level sensor encryptor. Chains the six primitives in the
2//! captured init.js (line 6050) into the single output the runtime
3//! POSTs to `/<tenant>/xhr/b/s`:
4//!
5//! ```text
6//! events_json ── jw(·, IS=50) ── h_p ── v_q(secret_feed, ·, offsets) ── payload
7//!                                          ▲
8//!                                          │
9//!                          v_n(secret_feed.len(), payload_b64.len(), cu)
10//!                                          ▲
11//!                                          │
12//!                          v_l(pf)  (= jw(b64(pf), VJ=10))
13//! ```
14
15use px_errors::AppError;
16
17use crate::cipher::b64::h_p;
18use crate::cipher::offsets::v_n;
19use crate::cipher::secret::v_l;
20use crate::cipher::splice::v_q;
21use crate::cipher::xor::{IS, jw};
22
23/// Encrypt a fully serialised sensor event batch.
24///
25/// * `events_json` — UTF-8 bytes of `JSON.stringify(events)` output
26///   (`hY` in the JS reference is JSON.stringify for our input shapes).
27/// * `pf` — `pf()` page-fingerprint bytes (or the tenant fallback when
28///   the runtime would have used `gC(365)`).
29/// * `cu` — the `ctx.cu` salt (the `vK` field).
30pub fn encrypt_sensor(events_json: &[u8], pf: &[u8], cu: &[u8]) -> Result<Vec<u8>, AppError> {
31    let secret_feed = v_l(pf);
32    let encrypted = h_p(&jw(events_json, IS)).into_bytes();
33    let offsets = v_n(secret_feed.len(), encrypted.len(), cu);
34    v_q(&secret_feed, &encrypted, &offsets)
35}
36
37#[cfg(test)]
38#[allow(clippy::expect_used)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn deterministic_for_same_inputs() {
44        let a = encrypt_sensor(b"[]", b"pedidosya.com.ar", b"cu-1").expect("encrypt");
45        let b = encrypt_sensor(b"[]", b"pedidosya.com.ar", b"cu-1").expect("encrypt");
46        assert_eq!(a, b);
47    }
48
49    #[test]
50    fn output_differs_for_distinct_pf() {
51        let a = encrypt_sensor(b"[]", b"pf-A", b"cu-shared").expect("encrypt");
52        let b = encrypt_sensor(b"[]", b"pf-B", b"cu-shared").expect("encrypt");
53        assert_ne!(a, b);
54    }
55}