Initial commit: Veritas Suite Main Server and Core Engine
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "veritas-core"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sha2.workspace = true
|
||||
rsa.workspace = true
|
||||
chrono.workspace = true
|
||||
anyhow.workspace = true
|
||||
@@ -0,0 +1,17 @@
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// Computes a unique hardware fingerprint (CPU / Machine identifier).
|
||||
pub fn generate_hardware_id() -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
let hostname = std::env::var("COMPUTERNAME")
|
||||
.or_else(|_| std::env::var("HOSTNAME"))
|
||||
.unwrap_or_else(|_| "UNKNOWN-HOST".to_string());
|
||||
|
||||
let username = std::env::var("USERNAME")
|
||||
.or_else(|_| std::env::var("USER"))
|
||||
.unwrap_or_else(|_| "UNKNOWN-USER".to_string());
|
||||
|
||||
let raw_id = format!("{}:{}", hostname, username);
|
||||
hasher.update(raw_id.as_bytes());
|
||||
format!("{:x}", hasher.finalize())
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod hwid;
|
||||
pub mod license;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ActivationRequest {
|
||||
pub license_key: String,
|
||||
pub hardware_id: String,
|
||||
pub app_name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ActivationResponse {
|
||||
pub success: bool,
|
||||
pub message: String,
|
||||
pub signed_token: Option<String>,
|
||||
pub expires_at: Option<chrono::DateTime<chrono::Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RegisterRequest {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LoginRequest {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AuthResponse {
|
||||
pub success: bool,
|
||||
pub message: String,
|
||||
pub user_id: Option<i32>,
|
||||
pub email: Option<String>,
|
||||
pub auth_token: Option<String>,
|
||||
pub is_admin: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UserLicenseInfo {
|
||||
pub license_key: String,
|
||||
pub plan_name: String,
|
||||
pub max_devices: i32,
|
||||
pub activated_devices: i64,
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UserDashboardResponse {
|
||||
pub success: bool,
|
||||
pub email: String,
|
||||
pub licenses: Vec<UserLicenseInfo>,
|
||||
}
|
||||
|
||||
// Admin Panel Structures
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AdminUserItem {
|
||||
pub id: i32,
|
||||
pub email: String,
|
||||
pub is_admin: bool,
|
||||
pub created_at: String,
|
||||
pub license_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AdminLicenseItem {
|
||||
pub id: i32,
|
||||
pub user_id: Option<i32>,
|
||||
pub user_email: Option<String>,
|
||||
pub license_key: String,
|
||||
pub plan_name: String,
|
||||
pub max_devices: i32,
|
||||
pub activated_devices: i64,
|
||||
pub active: bool,
|
||||
pub created_at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AdminStatsResponse {
|
||||
pub success: bool,
|
||||
pub total_users: i64,
|
||||
pub total_licenses: i64,
|
||||
pub total_activations: i64,
|
||||
pub users: Vec<AdminUserItem>,
|
||||
pub licenses: Vec<AdminLicenseItem>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CreateLicenseRequest {
|
||||
pub user_id: i32,
|
||||
pub plan_name: String,
|
||||
pub max_devices: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ToggleLicenseRequest {
|
||||
pub license_key: String,
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
// Download Center Structures
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SoftwareDownloadItem {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub category: String,
|
||||
pub file_size: String,
|
||||
pub download_url: String,
|
||||
pub description: String,
|
||||
pub is_available: bool,
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
use crate::{hwid::generate_hardware_id, ActivationRequest};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
pub struct LicenseClient {
|
||||
pub server_url: String,
|
||||
pub app_name: String,
|
||||
pub secret: String,
|
||||
}
|
||||
|
||||
impl LicenseClient {
|
||||
pub fn new(server_url: impl Into<String>, app_name: impl Into<String>) -> Self {
|
||||
Self {
|
||||
server_url: server_url.into(),
|
||||
app_name: app_name.into(),
|
||||
secret: "VERITAS_SECRET_KEY_SIGNING_2026".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_request(&self, license_key: &str) -> ActivationRequest {
|
||||
ActivationRequest {
|
||||
license_key: license_key.to_string(),
|
||||
hardware_id: generate_hardware_id(),
|
||||
app_name: self.app_name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_token_offline(&self, token: &str, license_key: &str, target_hwid: &str) -> bool {
|
||||
let parts: Vec<&str> = token.split(':').collect();
|
||||
if parts.len() != 4 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let token_key = parts[0];
|
||||
let token_hwid = parts[1];
|
||||
let token_exp: i64 = match parts[2].parse() {
|
||||
Ok(exp) => exp,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let token_sig = parts[3];
|
||||
|
||||
if token_key != license_key || token_hwid != target_hwid {
|
||||
return false;
|
||||
}
|
||||
|
||||
if chrono::Utc::now().timestamp() > token_exp {
|
||||
return false;
|
||||
}
|
||||
|
||||
let signature_input = format!(
|
||||
"{}:{}:{}:{}",
|
||||
token_key, token_hwid, token_exp, self.secret
|
||||
);
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(signature_input.as_bytes());
|
||||
let expected_sig = format!("{:x}", hasher.finalize());
|
||||
|
||||
token_sig == expected_sig
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_token_verification() {
|
||||
let client = LicenseClient::new("http://45.156.84.238", "VRE");
|
||||
let hwid = "WINDOWS-TEST-HWID-001";
|
||||
let key = "VERITAS-PRO-DEMO-2026";
|
||||
let exp = chrono::Utc::now().timestamp() + 3600;
|
||||
|
||||
let sig_input = format!("{}:{}:{}:{}", key, hwid, exp, client.secret);
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(sig_input.as_bytes());
|
||||
let sig = format!("{:x}", hasher.finalize());
|
||||
|
||||
let token = format!("{}:{}:{}:{}", key, hwid, exp, sig);
|
||||
|
||||
assert!(client.verify_token_offline(&token, key, hwid));
|
||||
assert!(!client.verify_token_offline(&token, "WRONG-KEY", hwid));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user