Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions examples/01_simple_detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ fn main() {
println!("Input: {:?}", input);

if let Some(hash) = cryptotrace::core::hashing::detect_hash(input) {
println!(" Hash: {} (confidence {:.2})", hash.algorithm, hash.confidence);
println!(
" Hash: {} (confidence {:.2})",
hash.algorithm, hash.confidence
);
}
if let Some(enc) = cryptotrace::core::encoding::detect_encoding(input) {
println!(" Encoding: {} (confidence {:.2})", enc.encoding_type, enc.confidence);
println!(
" Encoding: {} (confidence {:.2})",
enc.encoding_type, enc.confidence
);
}

let (entropy, _freq) = cryptotrace::core::entropy::shannon_entropy(input.as_bytes());
Expand Down
14 changes: 11 additions & 3 deletions examples/02_scan_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@ use std::fs;

fn main() {
let args: Vec<String> = env::args().collect();
let path = if args.len() > 1 { &args[1] } else { "Cargo.toml" };
let path = if args.len() > 1 {
&args[1]
} else {
"Cargo.toml"
};

let data = fs::read(path).expect("Failed to read file");

match cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
match cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary)
{
Ok(result) => {
println!("File: {}", path);
println!("Algorithm: {}", result.algorithm.unwrap_or_else(|| "<none>".into()));
println!(
"Algorithm: {}",
result.algorithm.unwrap_or_else(|| "<none>".into())
);
println!("Encoding: {}", result.detected_type);
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
println!("Entropy: {:.2}", entropy);
Expand Down
24 changes: 19 additions & 5 deletions examples/03_batch_folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ use std::fs;
fn main() {
let args: Vec<String> = env::args().collect();
let dir = if args.len() > 1 { &args[1] } else { "." };
let max_size: u64 = std::env::var("MAX_FILE_SIZE").ok().and_then(|s| s.parse().ok()).unwrap_or(10_485_760);
let max_size: u64 = std::env::var("MAX_FILE_SIZE")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10_485_760);

for entry in fs::read_dir(dir).unwrap().flatten() {
let path = entry.path();
if !path.is_file() { continue; }
if !path.is_file() {
continue;
}

let _meta = match fs::metadata(&path) {
Ok(m) if m.len() <= max_size => m,
Expand All @@ -20,12 +25,21 @@ fn main() {
Err(_) => continue,
};

match cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
match cryptotrace::analyzers::file::analyze_bytes(
&data,
cryptotrace::types::SourceType::Binary,
) {
Ok(result) => {
let algo = result.algorithm.unwrap_or_else(|| "-".into());
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
println!("{}\t{}\t{}\t{:.2}\t{:.2}",
path.display(), algo, result.detected_type, entropy, result.confidence);
println!(
"{}\t{}\t{}\t{:.2}\t{:.2}",
path.display(),
algo,
result.detected_type,
entropy,
result.confidence
);
}
Err(e) => eprintln!("Error scanning {}: {}", path.display(), e),
}
Expand Down
27 changes: 22 additions & 5 deletions examples/04_compare_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,37 @@ fn main() {

// Method 1: Raw bytes
println!("=== Raw bytes ===");
let r1 = cryptotrace::analyzers::file::analyze_bytes(test_data, cryptotrace::types::SourceType::Binary).unwrap();
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r1.algorithm, r1.detected_type, r1.entropy, r1.confidence);
let r1 = cryptotrace::analyzers::file::analyze_bytes(
test_data,
cryptotrace::types::SourceType::Binary,
)
.unwrap();
println!(
" algo={:?} type={} ent={:.2} conf={:.2}",
r1.algorithm, r1.detected_type, r1.entropy, r1.confidence
);

// Method 2: File
println!("=== From file ===");
let r2 = cryptotrace::analyzers::file::analyze_file(Path::new("Cargo.toml")).unwrap();
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r2.algorithm, r2.detected_type, r2.entropy, r2.confidence);
println!(
" algo={:?} type={} ent={:.2} conf={:.2}",
r2.algorithm, r2.detected_type, r2.entropy, r2.confidence
);

// Method 3: Stdin (if piped)
println!("=== Stdin (pipe data or skip) ===");
let mut buf = Vec::new();
if std::io::stdin().read_to_end(&mut buf).is_ok() && !buf.is_empty() {
let r3 = cryptotrace::analyzers::file::analyze_bytes(&buf, cryptotrace::types::SourceType::Binary).unwrap();
println!(" algo={:?} type={} ent={:.2} conf={:.2}", r3.algorithm, r3.detected_type, r3.entropy, r3.confidence);
let r3 = cryptotrace::analyzers::file::analyze_bytes(
&buf,
cryptotrace::types::SourceType::Binary,
)
.unwrap();
println!(
" algo={:?} type={} ent={:.2} conf={:.2}",
r3.algorithm, r3.detected_type, r3.entropy, r3.confidence
);
} else {
println!(" (no stdin data)");
}
Expand Down
23 changes: 18 additions & 5 deletions examples/05_csv_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,29 @@ fn main() {
let out = args.get(2).map(|s| s.as_str()).unwrap_or("scan_report.csv");

let mut wtr = csv::Writer::from_path(out).expect("Failed to create CSV");
wtr.write_record(["path", "algorithm", "detected_type", "entropy", "confidence", "risk_level"])
.unwrap();
wtr.write_record([
"path",
"algorithm",
"detected_type",
"entropy",
"confidence",
"risk_level",
])
.unwrap();

for entry in fs::read_dir(dir).unwrap().flatten() {
let path = entry.path();
if !path.is_file() { continue; }
if !path.is_file() {
continue;
}
let data = match fs::read(&path) {
Ok(d) if d.len() <= 10_485_760 => d,
_ => continue,
};
if let Ok(r) = cryptotrace::analyzers::file::analyze_bytes(&data, cryptotrace::types::SourceType::Binary) {
if let Ok(r) = cryptotrace::analyzers::file::analyze_bytes(
&data,
cryptotrace::types::SourceType::Binary,
) {
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
wtr.write_record([
path.to_string_lossy().as_ref(),
Expand All @@ -26,7 +38,8 @@ fn main() {
&format!("{:.4}", entropy),
&format!("{:.4}", r.confidence),
&format!("{:?}", r.risk_level),
]).ok();
])
.ok();
}
}
wtr.flush().ok();
Expand Down
31 changes: 24 additions & 7 deletions examples/06_recursive_decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,63 @@ fn main() {
// Gzip then base64 encode
let mut compressed = Vec::new();
{
let mut encoder = flate2::write::GzEncoder::new(&mut compressed, flate2::Compression::default());
let mut encoder =
flate2::write::GzEncoder::new(&mut compressed, flate2::Compression::default());
encoder.write_all(plaintext).unwrap();
encoder.finish().unwrap();
}

use base64::Engine;
let b64_payload = base64::engine::general_purpose::STANDARD.encode(&compressed);

println!("Encoded payload (first 80 chars): {:?}", &b64_payload[..80.min(b64_payload.len())]);
println!(
"Encoded payload (first 80 chars): {:?}",
&b64_payload[..80.min(b64_payload.len())]
);

// Decode layer by layer
let mut current = b64_payload.as_bytes().to_vec();
for layer in 1..=5 {
let s = String::from_utf8_lossy(&current);

if let Some(enc) = cryptotrace::core::encoding::detect_encoding(&s) {
println!("Layer {}: detected encoding = {} (conf={:.2})", layer, enc.encoding_type, enc.confidence);
println!(
"Layer {}: detected encoding = {} (conf={:.2})",
layer, enc.encoding_type, enc.confidence
);

match enc.encoding_type.as_str() {
"Base64" => {
if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(s.trim()) {
if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(s.trim())
{
current = decoded;
continue;
}
}
_ => { break; }
_ => {
break;
}
}
}

if cryptotrace::core::compression::detect_compression(&current).is_some() {
let mut decompressed = Vec::new();
let mut d = flate2::read::GzDecoder::new(std::io::Cursor::new(&current));
if d.read_to_end(&mut decompressed).is_ok() && !decompressed.is_empty() {
println!("Layer {}: gzip decompressed ({} bytes)", layer, decompressed.len());
println!(
"Layer {}: gzip decompressed ({} bytes)",
layer,
decompressed.len()
);
current = decompressed;
continue;
}
}
break;
}

println!("Final decoded text: {:?}", String::from_utf8_lossy(&current));
println!(
"Final decoded text: {:?}",
String::from_utf8_lossy(&current)
);
}
15 changes: 12 additions & 3 deletions examples/07_sandbox_crash_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ fn main() {
}
}
Err(e) => {
println!("Sandbox worker failed (expected if no worker binary): {}", e);
println!(
"Sandbox worker failed (expected if no worker binary): {}",
e
);
println!("Falling back to in-process analysis...");
match cryptotrace::analyzers::file::analyze_bytes(test_data, cryptotrace::types::SourceType::Binary) {
Ok(r) => println!("In-process result: algo={:?} ent={}", r.algorithm, r.entropy),
match cryptotrace::analyzers::file::analyze_bytes(
test_data,
cryptotrace::types::SourceType::Binary,
) {
Ok(r) => println!(
"In-process result: algo={:?} ent={}",
r.algorithm, r.entropy
),
Err(e2) => eprintln!("Fallback also failed: {}", e2),
}
}
Expand Down
21 changes: 17 additions & 4 deletions examples/08_confidence_calibration.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use cryptotrace::core::calibration::{generate_synthetic_dataset, train, predict_proba, signal_contributions, save_model, load_model};
use cryptotrace::core::calibration::{
generate_synthetic_dataset, load_model, predict_proba, save_model, signal_contributions, train,
};
use cryptotrace::types::SignalBreakdown;

fn main() {
Expand All @@ -8,7 +10,10 @@ fn main() {
println!(" {} samples generated", dataset.len());

let model = train(&dataset, 0.01, 1000, 0.001);
println!("Model trained: intercept={:.4}, weights={:?}", model.intercept, model.weights);
println!(
"Model trained: intercept={:.4}, weights={:?}",
model.intercept, model.weights
);
println!("Dataset size: {}", model.dataset_size);

let test_signals = SignalBreakdown {
Expand All @@ -26,12 +31,20 @@ fn main() {
let contribs = signal_contributions(&model, &test_signals);
println!("\nSignal contributions:");
for sc in &contribs {
println!(" {:20} {:>8} {:.4}", sc.signal_name, if sc.coefficient > 0.0 { "+" } else { "-" }, sc.contribution);
println!(
" {:20} {:>8} {:.4}",
sc.signal_name,
if sc.coefficient > 0.0 { "+" } else { "-" },
sc.contribution
);
}

save_model(&model, "calibration_example.json").ok();
if let Ok(loaded) = load_model("calibration_example.json") {
println!("\nModel save/load roundtrip: OK (weights={:?})", loaded.weights);
println!(
"\nModel save/load roundtrip: OK (weights={:?})",
loaded.weights
);
}
std::fs::remove_file("calibration_example.json").ok();
}
25 changes: 21 additions & 4 deletions examples/09_sliding_entropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,40 @@ use std::fs;

fn main() {
let args: Vec<String> = std::env::args().collect();
let path = if args.len() > 1 { &args[1] } else { "Cargo.toml" };
let path = if args.len() > 1 {
&args[1]
} else {
"Cargo.toml"
};
let data = fs::read(path).expect("Failed to read file");

println!("File: {} ({} bytes)", path, data.len());
let (entropy, _) = cryptotrace::core::entropy::shannon_entropy(&data);
println!("Global Shannon entropy: {:.2} bits/byte", entropy);

let sw = cryptotrace::core::sliding_entropy::sliding_window_entropy(&data, Some(4096), None, Some(7.5));
let sw = cryptotrace::core::sliding_entropy::sliding_window_entropy(
&data,
Some(4096),
None,
Some(7.5),
);

if sw.window_scores.is_empty() {
println!("File too small for any window");
return;
}

let avg: f64 = sw.window_scores.iter().sum::<f64>() / sw.window_scores.len() as f64;
let max_score = sw.window_scores.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let min_score = sw.window_scores.iter().cloned().fold(f64::INFINITY, f64::min);
let max_score = sw
.window_scores
.iter()
.cloned()
.fold(f64::NEG_INFINITY, f64::max);
let min_score = sw
.window_scores
.iter()
.cloned()
.fold(f64::INFINITY, f64::min);

println!("Windows analyzed: {}", sw.window_scores.len());
println!("Avg window entropy: {:.2}", avg);
Expand Down
Loading
Loading