feat: add decrypt-rs

This commit is contained in:
2023-02-16 00:43:18 +08:00
parent 297dae1aaa
commit f229156f70
4 changed files with 472 additions and 3 deletions

78
decrypt-rs/src/main.rs Executable file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env runrs
//! ```cargo
//! [dependencies]
//! aes-gcm = { version = "0.10.1", features = ["zeroize", "stream"] }
//! hex = "0.4.3"
//! rust_util = "0.6.41"
//! ```
use std::fs;
use aes_gcm::aead::Aead;
use aes_gcm::{Aes256Gcm, Key, KeyInit};
use rust_util::{failure_and_exit, information, opt_result, success, warning, XResult};
// see https://git.hatter.ink/hatter/crypto/src/branch/master/src/main/java/me/hatter/tools/crypto/stream/DecryptTool.java
fn main() -> XResult<()> {
let args: Vec<String> = std::env::args().skip(1).collect();
if args.len() != 3 {
failure_and_exit!("crypt.rs <key-hex> <file-in> <file-out>");
}
let key_bytes = opt_result!(hex::decode(&args[0]), "Decode key failed: {}");
if key_bytes.len() != 32 {
failure_and_exit!("Key length must be 32 bytes, but is: {}", key_bytes.len());
}
let file_in = &args[1];
let file_out = &args[2];
let file_in_meta = fs::metadata(file_in);
match file_in_meta {
Err(_) => failure_and_exit!("File in not exists: {}", file_in),
Ok(file_in_meta) => {
let file_in_len = file_in_meta.len();
if file_in_len < 100 * 1024 * 1024 {
success!("File in: {}, size: {}", file_in, file_in_len);
} else {
warning!("File in: {}, size: {}", file_in, file_in_len);
}
}
}
if is_file_exists(file_out) {
failure_and_exit!("File out exists: {}", file_out);
}
information!("Reading file in: {}", file_in);
let file_in_bytes = opt_result!(fs::read(&file_in), "Open file: {}, failed: {}", file_in);
let magic = &file_in_bytes[0..4];
let digest = &file_in_bytes[4..4 + 32];
information!("Magic: {}", hex::encode(magic));
information!("Key digest: {}", hex::encode(digest));
if hex::encode(magic) != "e2c50001" {
failure_and_exit!("Magic number error: {}", hex::encode(magic));
}
let mut nonce_bytes = [0_u8; 12];
for i in 0..12 {
nonce_bytes[i] = file_in_bytes[4 + 32 + i];
}
let file_in_bytes_content = &file_in_bytes[48..];
let key = Key::<Aes256Gcm>::from_slice(&key_bytes);
let nonce = nonce_bytes.into();
let aes256_gcm = Aes256Gcm::new(&key);
let decrypted = opt_result!(aes256_gcm.decrypt(&nonce, file_in_bytes_content), "Decrypt failed: {}");
information!("Writing file out: {}", file_out);
opt_result!(fs::write(&file_out, decrypted), "Write file out: {}, failed: {}", file_out);
success!("Write file out succeed!");
Ok(())
}
fn is_file_exists(file: &str) -> bool {
fs::metadata(file).is_ok()
}