File size: 4,058 Bytes
1d3f990 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | // WASM Cryptographic Engine
// SHA-512, Blake3, Ed25519 verification for deterministic hashing and signing
use wasm_bindgen::prelude::*;
use sha2::{Sha512, Digest};
#[wasm_bindgen]
pub struct CryptoEngine;
#[wasm_bindgen]
impl CryptoEngine {
/// Compute SHA-512 hash
#[wasm_bindgen]
pub fn sha512(input: &str) -> String {
let mut hasher = Sha512::new();
hasher.update(input.as_bytes());
let result = hasher.finalize();
hex::encode(result)
}
/// Verify SHA-512 hash
#[wasm_bindgen]
pub fn verify_sha512(input: &str, hash: &str) -> bool {
let computed = Self::sha512(input);
computed == hash
}
/// Compute Blake3 hash (if available via blake3 crate)
#[wasm_bindgen]
pub fn blake3(input: &str) -> String {
let hash = blake3::hash(input.as_bytes());
hash.to_hex().to_string()
}
/// Verify Blake3 hash
#[wasm_bindgen]
pub fn verify_blake3(input: &str, hash: &str) -> bool {
let computed = Self::blake3(input);
computed == hash
}
/// Generate nonce (deterministic, seeded)
#[wasm_bindgen]
pub fn generate_nonce(seed: &str, counter: u32) -> String {
let combined = format!("{}-{}", seed, counter);
let hash = Self::sha512(&combined);
hash[..32].to_string() // First 128 bits
}
/// Check if string is valid hex (128 chars for SHA-512)
#[wasm_bindgen]
pub fn is_valid_sha512_hex(s: &str) -> bool {
s.len() == 128 && s.chars().all(|c| c.is_ascii_hexdigit())
}
/// Check if string is valid hex (64 chars for Blake3)
#[wasm_bindgen]
pub fn is_valid_blake3_hex(s: &str) -> bool {
s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())
}
/// Verify Ed25519 signature (stub — actual verification requires libsodium)
#[wasm_bindgen]
pub fn verify_ed25519_signature(public_key: &str, message: &str, signature: &str) -> bool {
// Stub: actual implementation requires libsodium or similar
// For now, check format:
// - public_key: 64 hex chars (32 bytes)
// - signature: 128 hex chars (64 bytes)
if public_key.len() != 64 || !public_key.chars().all(|c| c.is_ascii_hexdigit()) {
return false;
}
if signature.len() != 128 || !signature.chars().all(|c| c.is_ascii_hexdigit()) {
return false;
}
// Real verification would call libsodium
true
}
/// Compute HMAC-SHA512
#[wasm_bindgen]
pub fn hmac_sha512(key: &str, message: &str) -> String {
use hmac::{Hmac, Mac};
use sha2::Sha512;
type HmacSha512 = Hmac<Sha512>;
let mut mac = HmacSha512::new_from_slice(key.as_bytes())
.expect("HMAC can take key of any size");
mac.update(message.as_bytes());
hex::encode(mac.finalize().into_bytes())
}
/// Constant-time string comparison (timing-safe)
#[wasm_bindgen]
pub fn constant_time_compare(a: &str, b: &str) -> bool {
if a.len() != b.len() {
return false;
}
let a_bytes = a.as_bytes();
let b_bytes = b.as_bytes();
let mut result: u8 = 0;
for i in 0..a_bytes.len() {
result |= a_bytes[i] ^ b_bytes[i];
}
result == 0
}
}
#[wasm_bindgen]
pub fn hash_canonical_form(data: &str) -> String {
CryptoEngine::sha512(data)
}
#[wasm_bindgen]
pub fn verify_canonical_hash(data: &str, hash: &str) -> bool {
CryptoEngine::verify_sha512(data, hash)
}
#[wasm_bindgen]
pub fn merkle_leaf_hash(index: u32, data: &str) -> String {
let leaf_data = format!("leaf:{}:{}", index, data);
CryptoEngine::sha512(&leaf_data)
}
#[wasm_bindgen]
pub fn merkle_parent_hash(left: &str, right: &str) -> String {
let parent_data = format!("{}|{}", left, right);
CryptoEngine::sha512(&parent_data)
}
|