1use std::fs::File;
2use std::io::{Read, Write, BufReader, BufWriter, Seek, SeekFrom};
3use std::path::Path;
4use aes::Aes256;
5use ctr::Ctr128BE;
6use ctr::cipher::{KeyIvInit, StreamCipher};
7use crate::crypto_utils::*;
8use crate::progress_utils::*;
9use crate::key_derivation;
10use crate::hmac_validator::HmacValidator;
11
12type Aes256Ctr = Ctr128BE<Aes256>;
13
14pub fn check_version(input_file_path: &str) -> Result<(), Box<dyn std::error::Error>> {
15 let input_path = Path::new(input_file_path);
16
17 let mut file = File::open(input_path)?;
19 let mut magic_number_bytes = vec![0u8; MAGIC_NUMBER.len()];
20 file.read_exact(&mut magic_number_bytes)?;
21
22 if magic_number_bytes != MAGIC_NUMBER.as_bytes() {
24 return Err("无效的加密文件格式".into());
25 }
26
27 let mut version = [0u8; 1];
29 file.read_exact(&mut version)?;
30 if version[0] != VERSION_SIGN {
31 return Err(format!("不支持的文件版本: {}", version[0]).into());
32 }
33
34 Ok(())
35}
36
37pub fn decrypt_with_mode(input_file_path: &str, output_file_path: &str, password: &str) -> Result<(), Box<dyn std::error::Error>> {
38 let input_path = Path::new(input_file_path);
39 let output_path = Path::new(output_file_path);
40
41 if !input_path.exists() || !input_path.is_file() {
42 return Err(format!("输入文件不存在: {}", input_file_path).into());
43 }
44
45 let start_time = start_timer();
47
48 let mut file = BufReader::with_capacity(BUFFER_SIZE, File::open(input_path)?);
50
51 file.seek(SeekFrom::Start((MAGIC_NUMBER.len() + 1) as u64))?;
53
54 let mut salt = vec![0u8; SALT_LENGTH];
56 file.read_exact(&mut salt)?;
57 let mut iv = vec![0u8; IV_LENGTH];
58 file.read_exact(&mut iv)?;
59
60 let master_key = key_derivation::derive_master_key(password.as_bytes(), &salt)?;
62
63 let (encryption_key, hmac_key) = key_derivation::derive_encryption_and_hmac_keys(&master_key)?;
65
66 let total_file_length = input_path.metadata()?.len();
68 let header_length = (MAGIC_NUMBER.len() + 1 + SALT_LENGTH + IV_LENGTH) as u64;
69 let hmac_length = 32u64; let encrypted_data_length = total_file_length - header_length - hmac_length;
71
72 let mut output_file = File::create(output_path)?;
74 let mut writer = BufWriter::with_capacity(BUFFER_SIZE, &mut output_file);
75
76 let parallel_parts = get_parts();
78
79 let mut single_cipher = if parallel_parts == 1 {
80 Some(Aes256Ctr::new(encryption_key.as_slice().into(), iv.as_slice().into()))
81 } else { None };
82
83 let mut hmac = HmacValidator::new(&hmac_key)?;
85
86 let mut buffer = vec![0u8; BUFFER_SIZE];
88 let mut total_read = 0;
89
90 while total_read < encrypted_data_length {
91 let bytes_to_read = std::cmp::min(BUFFER_SIZE as u64, encrypted_data_length - total_read) as usize;
92 let bytes_read = file.read(&mut buffer[..bytes_to_read])?;
93
94 if bytes_read == 0 {
95 break;
96 }
97
98 let chunk = &mut buffer[..bytes_read];
99
100 hmac.update(chunk);
102
103 if parallel_parts == 1 {
104 if let Some(cipher) = &mut single_cipher { cipher.apply_keystream(chunk); }
105 } else {
106 crate::parallel_handler::ctr_apply_in_parts(
107 encryption_key.as_slice(),
108 iv.as_slice(),
109 chunk,
110 total_read as usize
111 ).map_err(|e| format!("parallel decrypt error: {}", e))?;
112 }
113
114 writer.write_all(chunk)?;
116
117 total_read += bytes_read as u64;
118
119 update_progress(total_read, encrypted_data_length);
121 }
122
123 let mut stored_hmac = vec![0u8; hmac_length as usize];
125 file.read_exact(&mut stored_hmac)?;
126
127 hmac.verify(&stored_hmac)?;
129
130 writer.flush()?;
131
132 let duration = start_time.elapsed();
134 update_progress(encrypted_data_length, encrypted_data_length);
135 println!("\u{001B}[0mDEC!: Done in {}", format_duration(duration));
136
137 Ok(())
138}