Initial ChronoSeal release
This commit is contained in:
commit
a66debdece
48 files changed
+2362
No files matched your search
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "shared"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1" # <- add this line
|
||||
blake3 = "1"
|
||||
hex = "0.4"
|
||||
base64 = "0.22"
|
||||
rand = "0.8"
|
||||
ed25519-dalek = { version = "2", features = ["rand_core"] }
|
||||
@@ -0,0 +1,11 @@
|
||||
pub const SESSION_ID_LEN: usize = 32;
|
||||
pub const SALT_LEN: usize = 16;
|
||||
pub const HEARTBEAT_MIN_INTERVAL_MS: u64 = 12_000;
|
||||
pub const HEARTBEAT_MAX_INTERVAL_MS: u64 = 25_000;
|
||||
pub const EXPIRATION_MINUTES: i64 = 30;
|
||||
pub const RATE_LIMIT_COUNT: u32 = 5;
|
||||
pub const RATE_LIMIT_WINDOW_SECS: u64 = 10;
|
||||
pub const MAX_TIMESTAMP_DRIFT_MS: i64 = 30_000;
|
||||
pub const MIN_MOUSE_TOTAL_DIST: f64 = 10.0;
|
||||
pub const MAX_MOUSE_AVG_SPEED: f64 = 2.0; // px/ms
|
||||
pub const MIN_PAUSE_COUNT: u32 = 1;
|
||||
@@ -0,0 +1,42 @@
|
||||
use blake3::Hasher;
|
||||
use crate::protocol::{EntropyData, StackState};
|
||||
|
||||
/// Initial hash for a brand-new session: Blake3(session_id || pub_key || salt)
|
||||
pub fn initial_hash(session_id: &str, pub_key: &[u8], salt: &[u8]) -> Vec<u8> {
|
||||
let mut h = Hasher::new();
|
||||
h.update(session_id.as_bytes());
|
||||
h.update(pub_key);
|
||||
h.update(salt);
|
||||
h.finalize().as_bytes().to_vec()
|
||||
}
|
||||
|
||||
/// Next hash in the chain: Blake3 with the salt mixed in (no keyed mode needed)
|
||||
pub fn next_chain_hash(
|
||||
prev_hash: &[u8],
|
||||
timestamp: u64,
|
||||
entropy: &EntropyData,
|
||||
stack: &StackState,
|
||||
salt: &[u8],
|
||||
) -> Vec<u8> {
|
||||
let entropy_json = serde_json::to_string(entropy).unwrap();
|
||||
let stack_json = serde_json::to_string(stack).unwrap();
|
||||
|
||||
let entropy_hash = blake3::hash(entropy_json.as_bytes());
|
||||
let stack_hash = blake3::hash(stack_json.as_bytes());
|
||||
|
||||
let mut h = Hasher::new();
|
||||
// Mix the salt into the hash state
|
||||
h.update(salt);
|
||||
h.update(prev_hash);
|
||||
h.update(×tamp.to_le_bytes());
|
||||
h.update(entropy_hash.as_bytes());
|
||||
h.update(stack_hash.as_bytes());
|
||||
h.finalize().as_bytes().to_vec()
|
||||
}
|
||||
|
||||
/// Hash of all stack items for VM HASH opcode
|
||||
pub fn hash_stack(stack: &[u32]) -> u32 {
|
||||
let data: Vec<u8> = stack.iter().flat_map(|x| x.to_le_bytes()).collect();
|
||||
let hash = blake3::hash(&data);
|
||||
u32::from_le_bytes(hash.as_bytes()[..4].try_into().unwrap())
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod constants;
|
||||
pub mod hashing;
|
||||
pub mod protocol;
|
||||
@@ -0,0 +1,62 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct InitRequest {
|
||||
pub public_key: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct InitResponse {
|
||||
pub session_id: String,
|
||||
pub salt: String,
|
||||
pub opcodes_b64: String,
|
||||
pub initial_hash: String,
|
||||
pub expires_at: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct HeartbeatRequest {
|
||||
pub session_id: String,
|
||||
pub prev_hash: String,
|
||||
pub timestamp: u64,
|
||||
pub entropy_data: EntropyData,
|
||||
pub stack_state: StackState,
|
||||
pub fingerprint: Fingerprint,
|
||||
pub signature: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct HeartbeatResponse {
|
||||
pub status: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_salt: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Fingerprint {
|
||||
#[serde(rename = "aspectRatio")]
|
||||
pub aspect_ratio: String,
|
||||
#[serde(rename = "devicePixelRatio")]
|
||||
pub device_pixel_ratio: String,
|
||||
#[serde(rename = "hardwareConcurrency")]
|
||||
pub hardware_concurrency: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct EntropyData {
|
||||
pub events: Vec<MouseEvent>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
pub struct MouseEvent {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
#[serde(rename = "t")]
|
||||
pub timestamp_ms: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct StackState {
|
||||
pub stack: Vec<u32>,
|
||||
pub ip: u16,
|
||||
}
|
||||
Reference in new issue
Block a user