Skip to main content

excelize_rs/
crypt.rs

1//! Workbook encryption / decryption (`crypt.go`).
2//!
3//! Provides ECMA-376 agile and standard encryption helpers, CFB packaging
4//! and the ISO password hashing algorithm used for sheet/workbook protection.
5
6use std::io::{Cursor, Read, Write};
7
8use aes::cipher::KeyInit;
9use aes::cipher::generic_array::GenericArray;
10use aes::cipher::{BlockDecrypt, BlockEncrypt};
11use aes::{Aes128, Aes192, Aes256};
12use base64::Engine as _;
13use quick_xml::de::from_reader as xml_from_reader;
14use rand::RngCore;
15use serde::Deserialize;
16
17use crate::constants::MAX_FIELD_LENGTH;
18use crate::errors::{
19    ErrPasswordLengthInvalid, ErrUnknownEncryptMechanism, ErrUnsupportedEncryptMechanism,
20    ErrUnsupportedHashAlgorithm, ErrWorkbookFileFormat, Result,
21};
22use crate::lib_util::count_utf16_string;
23use crate::options::Options;
24
25// ------------------------------------------------------------------
26// Constants
27// ------------------------------------------------------------------
28
29const BLOCK_KEY: &[u8] = &[0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6];
30#[allow(dead_code)]
31const DIF_SECT: u32 = 0xFFFFFFFC;
32#[allow(dead_code)]
33const END_OF_CHAIN: u32 = 0xFFFFFFFE;
34#[allow(dead_code)]
35const FAT_SECT: u32 = 0xFFFFFFFD;
36const ITER_COUNT: usize = 50_000;
37const PACKAGE_ENCRYPTION_CHUNK_SIZE: usize = 4096;
38const PACKAGE_OFFSET: usize = 8;
39const _SHEET_PROTECTION_SPIN_COUNT: i32 = 100_000;
40const _WORKBOOK_PROTECTION_SPIN_COUNT: i32 = 100_000;
41
42// ------------------------------------------------------------------
43// XML encryption info types
44// ------------------------------------------------------------------
45
46/// Top-level encryption info container used by ECMA-376 agile encryption.
47#[derive(Debug, Default, Deserialize)]
48#[serde(rename = "encryption")]
49pub struct Encryption {
50    #[serde(rename = "keyData", default)]
51    pub key_data: KeyData,
52    #[serde(rename = "dataIntegrity", default)]
53    pub data_integrity: DataIntegrity,
54    #[serde(rename = "keyEncryptors", default)]
55    pub key_encryptors: KeyEncryptors,
56}
57
58/// Cryptographic attributes used to encrypt the data.
59#[derive(Debug, Default, Deserialize)]
60#[serde(rename = "keyData")]
61pub struct KeyData {
62    #[serde(rename = "@saltSize", default)]
63    pub salt_size: i32,
64    #[serde(rename = "@blockSize", default)]
65    pub block_size: i32,
66    #[serde(rename = "@keyBits", default)]
67    pub key_bits: i32,
68    #[serde(rename = "@hashSize", default)]
69    pub hash_size: i32,
70    #[serde(rename = "@cipherAlgorithm", default)]
71    pub cipher_algorithm: String,
72    #[serde(rename = "@cipherChaining", default)]
73    pub cipher_chaining: String,
74    #[serde(rename = "@hashAlgorithm", default)]
75    pub hash_algorithm: String,
76    #[serde(rename = "@saltValue", default)]
77    pub salt_value: String,
78}
79
80/// Encrypted copies of the salt/hash values used for integrity checks.
81#[derive(Debug, Default, Deserialize)]
82#[serde(rename = "dataIntegrity")]
83pub struct DataIntegrity {
84    #[serde(rename = "@encryptedHmacKey", default)]
85    pub encrypted_hmac_key: String,
86    #[serde(rename = "@encryptedHmacValue", default)]
87    pub encrypted_hmac_value: String,
88}
89
90/// Collection of key encryptors.
91#[derive(Debug, Default, Deserialize)]
92#[serde(rename = "keyEncryptors")]
93pub struct KeyEncryptors {
94    #[serde(rename = "keyEncryptor", default)]
95    pub key_encryptor: Vec<KeyEncryptor>,
96}
97
98/// A single key encryptor entry.
99#[derive(Debug, Default, Deserialize)]
100#[serde(rename = "keyEncryptor")]
101pub struct KeyEncryptor {
102    #[serde(rename = "@uri", default)]
103    pub uri: String,
104    #[serde(rename = "encryptedKey")]
105    pub encrypted_key: EncryptedKey,
106}
107
108/// Encrypted key used to derive the package encryption key.
109#[derive(Debug, Default, Deserialize)]
110#[serde(rename = "encryptedKey")]
111pub struct EncryptedKey {
112    #[serde(rename = "@spinCount", default)]
113    pub spin_count: i32,
114    #[serde(rename = "@encryptedVerifierHashInput", default)]
115    pub encrypted_verifier_hash_input: String,
116    #[serde(rename = "@encryptedVerifierHashValue", default)]
117    pub encrypted_verifier_hash_value: String,
118    #[serde(rename = "@encryptedKeyValue", default)]
119    pub encrypted_key_value: String,
120    // KeyData fields are duplicated on the encryptedKey element in agile
121    // encryption info XML.
122    #[serde(rename = "@saltSize", default)]
123    pub salt_size: i32,
124    #[serde(rename = "@blockSize", default)]
125    pub block_size: i32,
126    #[serde(rename = "@keyBits", default)]
127    pub key_bits: i32,
128    #[serde(rename = "@hashSize", default)]
129    pub hash_size: i32,
130    #[serde(rename = "@cipherAlgorithm", default)]
131    pub cipher_algorithm: String,
132    #[serde(rename = "@cipherChaining", default)]
133    pub cipher_chaining: String,
134    #[serde(rename = "@hashAlgorithm", default)]
135    pub hash_algorithm: String,
136    #[serde(rename = "@saltValue", default)]
137    pub salt_value: String,
138}
139
140// ------------------------------------------------------------------
141// Standard encryption header / verifier
142// ------------------------------------------------------------------
143
144#[derive(Debug, Default)]
145pub struct StandardEncryptionHeader {
146    pub flags: u32,
147    pub size_extra: u32,
148    pub alg_id: u32,
149    pub alg_id_hash: u32,
150    pub key_size: u32,
151    pub provider_type: u32,
152    pub reserved1: u32,
153    pub reserved2: u32,
154    pub csp_name: String,
155}
156
157#[derive(Debug, Default)]
158pub struct StandardEncryptionVerifier {
159    pub salt_size: u32,
160    pub salt: Vec<u8>,
161    pub encrypted_verifier: Vec<u8>,
162    pub verifier_hash_size: u32,
163    pub encrypted_verifier_hash: Vec<u8>,
164}
165
166/// Internal encryption state used by the standard encryptor.
167#[derive(Debug)]
168struct EncryptionInfo {
169    block_size: usize,
170    salt_size: usize,
171    encrypted_key_value: Vec<u8>,
172    encrypted_verifier_hash_input: Vec<u8>,
173    encrypted_verifier_hash_value: Vec<u8>,
174    salt_value: Vec<u8>,
175    key_bits: u32,
176}
177
178// ------------------------------------------------------------------
179// Public API
180// ------------------------------------------------------------------
181
182/// Decrypt a CFB-encoded workbook package.
183///
184/// Supports ECMA-376 agile and standard encryption with MD4, MD5,
185/// RIPEMD-160, SHA1, SHA256, SHA384 and SHA512 hash algorithms.
186pub fn decrypt(raw: &[u8], opts: &Options) -> Result<Vec<u8>> {
187    let mut doc = open_cfb(raw)?;
188    let (encryption_info_buf, encrypted_package_buf) = extract_part(&mut doc)?;
189    let mechanism = encryption_mechanism(&encryption_info_buf)?;
190    match mechanism.as_str() {
191        "agile" => agile_decrypt(&encryption_info_buf, &encrypted_package_buf, opts),
192        "standard" => standard_decrypt(&encryption_info_buf, &encrypted_package_buf, opts),
193        _ => Err(Box::new(ErrUnsupportedEncryptMechanism)),
194    }
195}
196
197/// Encrypt a workbook package with a password using ECMA-376 standard
198/// encryption (AES-128).
199pub fn encrypt(raw: &[u8], opts: &Options) -> Result<Vec<u8>> {
200    let mut encryptor = EncryptionInfo {
201        encrypted_verifier_hash_input: vec![0; 16],
202        encrypted_verifier_hash_value: vec![0; 32],
203        salt_value: vec![0; 16],
204        block_size: 16,
205        key_bits: 128,
206        salt_size: 16,
207        encrypted_key_value: Vec::new(),
208    };
209
210    let encryption_info_buffer = encryptor.standard_key_encryption(&opts.password)?;
211    let mut encrypted_package: Vec<u8> = Vec::with_capacity(8 + raw.len() + 16);
212    encrypted_package.extend_from_slice(&(raw.len() as u64).to_le_bytes());
213    encrypted_package.extend_from_slice(&encryptor.encrypt(raw));
214
215    let cursor = Cursor::new(Vec::new());
216    let mut compound_file = cfb::CompoundFile::create(cursor)?;
217    {
218        let mut stream = compound_file.create_stream("/EncryptionInfo")?;
219        stream.write_all(&encryption_info_buffer)?;
220    }
221    {
222        let mut stream = compound_file.create_stream("/EncryptedPackage")?;
223        stream.write_all(&encrypted_package)?;
224    }
225    compound_file.flush()?;
226    Ok(compound_file.into_inner().into_inner())
227}
228
229// ------------------------------------------------------------------
230// CFB helpers
231// ------------------------------------------------------------------
232
233fn open_cfb(raw: &[u8]) -> Result<cfb::CompoundFile<Cursor<Vec<u8>>>> {
234    let cursor = Cursor::new(raw.to_vec());
235    match cfb::CompoundFile::open(cursor) {
236        Ok(doc) => Ok(doc),
237        Err(e) => {
238            let msg = e.to_string();
239            let re = regex::Regex::new(r"FAT has (\d+) entries, but file has only (\d+) sectors")
240                .unwrap();
241            if let Some(caps) = re.captures(&msg) {
242                let fat_entries: usize = caps[1].parse().unwrap_or(0);
243                if fat_entries > 0 {
244                    let sector_size = 1usize << (raw.get(0x1E).copied().unwrap_or(9) as usize);
245                    let required_len = (fat_entries + 1) * sector_size;
246                    if raw.len() < required_len {
247                        let mut padded = raw.to_vec();
248                        padded.resize(required_len, 0);
249                        let cursor = Cursor::new(padded);
250                        return Ok(cfb::CompoundFile::open(cursor)?);
251                    }
252                }
253            }
254            Err(Box::new(e))
255        }
256    }
257}
258
259fn extract_part(doc: &mut cfb::CompoundFile<Cursor<Vec<u8>>>) -> Result<(Vec<u8>, Vec<u8>)> {
260    let mut encryption_info_buf = Vec::new();
261    let mut encrypted_package_buf = Vec::new();
262
263    if let Ok(mut stream) = doc.open_stream("/EncryptionInfo") {
264        stream.read_to_end(&mut encryption_info_buf)?;
265    }
266    if let Ok(mut stream) = doc.open_stream("/EncryptedPackage") {
267        stream.read_to_end(&mut encrypted_package_buf)?;
268    }
269
270    if encryption_info_buf.is_empty() || encrypted_package_buf.is_empty() {
271        return Err(Box::new(ErrWorkbookFileFormat));
272    }
273    Ok((encryption_info_buf, encrypted_package_buf))
274}
275
276fn encryption_mechanism(buffer: &[u8]) -> Result<String> {
277    if buffer.len() < 4 {
278        return Err(Box::new(ErrUnknownEncryptMechanism));
279    }
280    let version_major = u16::from_le_bytes([buffer[0], buffer[1]]);
281    let version_minor = u16::from_le_bytes([buffer[2], buffer[3]]);
282
283    if version_major == 4 && version_minor == 4 {
284        return Ok("agile".to_string());
285    }
286    if (2..=4).contains(&version_major) && version_minor == 2 {
287        return Ok("standard".to_string());
288    }
289    if (version_major == 3 || version_major == 4) && version_minor == 3 {
290        return Err(Box::new(ErrUnsupportedEncryptMechanism));
291    }
292    Err(Box::new(ErrUnsupportedEncryptMechanism))
293}
294
295// ------------------------------------------------------------------
296// ECMA-376 standard encryption
297// ------------------------------------------------------------------
298
299fn standard_decrypt(
300    encryption_info_buf: &[u8],
301    encrypted_package_buf: &[u8],
302    opts: &Options,
303) -> Result<Vec<u8>> {
304    if encryption_info_buf.len() < 12 {
305        return Err(Box::new(ErrWorkbookFileFormat));
306    }
307    let encryption_header_size = u32::from_le_bytes([
308        encryption_info_buf[8],
309        encryption_info_buf[9],
310        encryption_info_buf[10],
311        encryption_info_buf[11],
312    ]) as usize;
313    if 12 + encryption_header_size > encryption_info_buf.len() {
314        return Err(Box::new(ErrWorkbookFileFormat));
315    }
316    let block = &encryption_info_buf[12..12 + encryption_header_size];
317    let header = standard_encryption_header(block)?;
318    let verifier_block = &encryption_info_buf[12 + encryption_header_size..];
319    let algorithm = if matches!(header.alg_id, 0x0000_660E | 0x0000_660F | 0x0000_6610) {
320        "AES"
321    } else {
322        "RC4"
323    };
324    let verifier = standard_encryption_verifier(algorithm, verifier_block);
325    let secret_key = standard_convert_passwd_to_key(&header, &verifier, opts)?;
326
327    let x = &encrypted_package_buf[8..];
328    let decrypted = match secret_key.len() {
329        16 => decrypt_aes_ecb(
330            Aes128::new_from_slice(&secret_key).map_err(|e| {
331                std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
332            })?,
333            x,
334        ),
335        24 => decrypt_aes_ecb(
336            Aes192::new_from_slice(&secret_key).map_err(|e| {
337                std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
338            })?,
339            x,
340        ),
341        32 => decrypt_aes_ecb(
342            Aes256::new_from_slice(&secret_key).map_err(|e| {
343                std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
344            })?,
345            x,
346        ),
347        _ => {
348            return Err(Box::new(std::io::Error::new(
349                std::io::ErrorKind::InvalidData,
350                format!(
351                    "unsupported standard encryption key size: {}",
352                    header.key_size
353                ),
354            )));
355        }
356    };
357    Ok(decrypted)
358}
359
360fn decrypt_aes_ecb<C: BlockDecrypt>(cipher: C, input: &[u8]) -> Vec<u8> {
361    let mut decrypted = vec![0u8; input.len()];
362    for (src, dst) in input.chunks(16).zip(decrypted.chunks_mut(16)) {
363        let mut block = [0u8; 16];
364        block[..src.len()].copy_from_slice(src);
365        cipher.decrypt_block(GenericArray::from_mut_slice(&mut block));
366        dst.copy_from_slice(&block);
367    }
368    decrypted
369}
370
371fn standard_encryption_header(block: &[u8]) -> Result<StandardEncryptionHeader> {
372    if block.len() < 32 {
373        return Err(Box::new(ErrWorkbookFileFormat));
374    }
375    let csp_name = String::from_utf8_lossy(&block[32..]).to_string();
376    Ok(StandardEncryptionHeader {
377        flags: u32::from_le_bytes([block[0], block[1], block[2], block[3]]),
378        size_extra: u32::from_le_bytes([block[4], block[5], block[6], block[7]]),
379        alg_id: u32::from_le_bytes([block[8], block[9], block[10], block[11]]),
380        alg_id_hash: u32::from_le_bytes([block[12], block[13], block[14], block[15]]),
381        key_size: u32::from_le_bytes([block[16], block[17], block[18], block[19]]),
382        provider_type: u32::from_le_bytes([block[20], block[21], block[22], block[23]]),
383        reserved1: u32::from_le_bytes([block[24], block[25], block[26], block[27]]),
384        reserved2: u32::from_le_bytes([block[28], block[29], block[30], block[31]]),
385        csp_name,
386    })
387}
388
389fn standard_encryption_verifier(algorithm: &str, blob: &[u8]) -> StandardEncryptionVerifier {
390    let salt_size = u32::from_le_bytes([blob[0], blob[1], blob[2], blob[3]]);
391    let salt_end = 4 + salt_size as usize;
392    let salt = blob[4..salt_end].to_vec();
393    let verifier_end = salt_end + 16;
394    let encrypted_verifier = blob[salt_end..verifier_end].to_vec();
395    let verifier_hash_size = u32::from_le_bytes([
396        blob[verifier_end],
397        blob[verifier_end + 1],
398        blob[verifier_end + 2],
399        blob[verifier_end + 3],
400    ]);
401    let hash_end = match algorithm {
402        "RC4" => verifier_end + 4 + 20,
403        _ => verifier_end + 4 + 32,
404    };
405    let encrypted_verifier_hash = blob[verifier_end + 4..hash_end].to_vec();
406    StandardEncryptionVerifier {
407        salt_size,
408        salt,
409        encrypted_verifier,
410        verifier_hash_size,
411        encrypted_verifier_hash,
412    }
413}
414
415fn standard_convert_passwd_to_key(
416    header: &StandardEncryptionHeader,
417    verifier: &StandardEncryptionVerifier,
418    opts: &Options,
419) -> Result<Vec<u8>> {
420    let password_buffer = encode_utf16le(&opts.password);
421    let mut key = hashing("sha1", &[&verifier.salt, &password_buffer]);
422    for i in 0..ITER_COUNT {
423        let iterator = create_uint32_le_buffer(i as i32, 4);
424        key = hashing("sha1", &[&iterator, &key]);
425    }
426    let block = 0i32;
427    let h_final = hashing("sha1", &[&key, &create_uint32_le_buffer(block, 4)]);
428    let cb_required_key_length = (header.key_size / 8) as usize;
429    let cb_hash = 20; // SHA1 digest size
430
431    let buf1 = vec![0x36u8; 64];
432    let xored = standard_xor_bytes(&h_final, &buf1[..cb_hash]);
433    let mut buf1 = Vec::with_capacity(64);
434    buf1.extend_from_slice(&xored);
435    buf1.extend_from_slice(&vec![0x36u8; 64 - cb_hash]);
436    let x1 = hashing("sha1", &[&buf1]);
437
438    let buf2 = vec![0x5cu8; 64];
439    let xored = standard_xor_bytes(&h_final, &buf2[..cb_hash]);
440    let mut buf2 = Vec::with_capacity(64);
441    buf2.extend_from_slice(&xored);
442    buf2.extend_from_slice(&vec![0x5cu8; 64 - cb_hash]);
443    let x2 = hashing("sha1", &[&buf2]);
444
445    let mut x3 = x1;
446    x3.extend_from_slice(&x2);
447    Ok(x3[..cb_required_key_length].to_vec())
448}
449
450fn standard_xor_bytes(a: &[u8], b: &[u8]) -> Vec<u8> {
451    a.iter().zip(b.iter()).map(|(x, y)| x ^ y).collect()
452}
453
454impl EncryptionInfo {
455    fn encrypt(&self, input: &[u8]) -> Vec<u8> {
456        let input_bytes = if input.len() % self.block_size == 0 {
457            input.len()
458        } else {
459            input.len() + self.block_size - (input.len() % self.block_size)
460        };
461        let cipher = Aes128::new_from_slice(&self.encrypted_key_value).expect("valid AES key");
462        let mut output = Vec::with_capacity(input_bytes);
463        for i in (0..input_bytes).step_by(self.block_size) {
464            let mut chunk = [0u8; 16];
465            let end = (i + self.block_size).min(input.len());
466            chunk[..end - i].copy_from_slice(&input[i..end]);
467            cipher.encrypt_block(GenericArray::from_mut_slice(&mut chunk));
468            output.extend_from_slice(&chunk);
469        }
470        output
471    }
472
473    fn standard_key_encryption(&mut self, password: &str) -> Result<Vec<u8>> {
474        if count_utf16_string(password) == 0 || count_utf16_string(password) > MAX_FIELD_LENGTH {
475            return Err(Box::new(ErrPasswordLengthInvalid));
476        }
477        let mut stream = ByteWriter::new();
478        stream.write_uint16(0x0003);
479        stream.write_uint16(0x0002);
480        stream.write_uint32(0x24);
481        stream.write_uint32(0xA4);
482        stream.write_uint32(0x24);
483        stream.write_uint32(0x00);
484        stream.write_uint32(0x660E);
485        stream.write_uint32(0x8004);
486        stream.write_uint32(0x80);
487        stream.write_uint32(0x18);
488        stream.write_uint64(0x00);
489        let provider_name = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)";
490        stream.write_utf16le(provider_name);
491        stream.write_uint16(0x00);
492        stream.write_uint32(0x10);
493
494        let key_data_salt_value = random_bytes(self.salt_size)?;
495        let verifier_hash_input = random_bytes(16)?;
496        self.salt_value = key_data_salt_value;
497        self.encrypted_key_value = standard_convert_passwd_to_key(
498            &StandardEncryptionHeader {
499                key_size: self.key_bits,
500                ..Default::default()
501            },
502            &StandardEncryptionVerifier {
503                salt: self.salt_value.clone(),
504                ..Default::default()
505            },
506            &Options {
507                password: password.to_string(),
508                ..Default::default()
509            },
510        )?;
511        let verifier_hash_input_key = hashing("sha1", &[&verifier_hash_input]);
512        self.encrypted_verifier_hash_input = self.encrypt(&verifier_hash_input);
513        self.encrypted_verifier_hash_value = self.encrypt(&verifier_hash_input_key);
514
515        stream.write_bytes(&self.salt_value);
516        stream.write_bytes(&self.encrypted_verifier_hash_input);
517        stream.write_uint32(0x14);
518        stream.write_bytes(&self.encrypted_verifier_hash_value);
519        Ok(stream.into_inner())
520    }
521}
522
523// ------------------------------------------------------------------
524// ECMA-376 agile encryption
525// ------------------------------------------------------------------
526
527fn agile_decrypt(
528    encryption_info_buf: &[u8],
529    encrypted_package_buf: &[u8],
530    opts: &Options,
531) -> Result<Vec<u8>> {
532    let encryption_info = parse_encryption_info(&encryption_info_buf[8..])?;
533    let key = convert_passwd_to_key(&opts.password, BLOCK_KEY, &encryption_info)?;
534    let encrypted_key = &encryption_info.key_encryptors.key_encryptor[0].encrypted_key;
535    let salt_value = base64_decode(&encrypted_key.salt_value)?;
536    let encrypted_key_value = base64_decode(&encrypted_key.encrypted_key_value)?;
537    let package_key = decrypt_aes_cbc(&key, &salt_value, &encrypted_key_value)?;
538    decrypt_package(&package_key, encrypted_package_buf, &encryption_info)
539}
540
541fn convert_passwd_to_key(
542    passwd: &str,
543    block_key: &[u8],
544    encryption: &Encryption,
545) -> Result<Vec<u8>> {
546    let encrypted_key = &encryption.key_encryptors.key_encryptor[0].encrypted_key;
547    let salt_value = base64_decode(&encrypted_key.salt_value)?;
548    let mut buffer = Vec::with_capacity(salt_value.len() + passwd.len() * 2);
549    buffer.extend_from_slice(&salt_value);
550    buffer.extend_from_slice(&encode_utf16le(passwd));
551
552    let mut key = hashing(&encryption.key_data.hash_algorithm, &[&buffer]);
553    for i in 0..encrypted_key.spin_count {
554        let iterator = create_uint32_le_buffer(i, 4);
555        key = hashing(&encryption.key_data.hash_algorithm, &[&iterator, &key]);
556    }
557    key = hashing(&encryption.key_data.hash_algorithm, &[&key, block_key]);
558
559    let key_bytes = (encrypted_key.key_bits / 8) as usize;
560    if key.len() < key_bytes {
561        key.extend_from_slice(&vec![0x36u8; 0x36]);
562    } else if key.len() > key_bytes {
563        key.truncate(key_bytes);
564    }
565    Ok(key)
566}
567
568fn parse_encryption_info(encryption_info: &[u8]) -> Result<Encryption> {
569    let xml = String::from_utf8_lossy(encryption_info);
570    let stripped = strip_encryption_namespaces(&xml);
571    Ok(xml_from_reader(stripped.as_bytes())?)
572}
573
574fn strip_encryption_namespaces(xml: &str) -> String {
575    let mut s = xml.to_string();
576    for ns in [
577        "xmlns=\"http://schemas.microsoft.com/office/2006/encryption\"",
578        "xmlns:p=\"http://schemas.microsoft.com/office/2006/keyEncryptor/password\"",
579    ] {
580        s = s.replace(ns, "");
581    }
582    // Remove the "p:" prefix from element and attribute names without
583    // corrupting attribute values such as "http://...".
584    let re = regex::Regex::new(r#"(</?|[\s])p:"#).unwrap();
585    re.replace_all(&s, "$1").to_string()
586}
587
588fn decrypt_aes_cbc(key: &[u8], iv: &[u8], input: &[u8]) -> Result<Vec<u8>> {
589    let mut output = input.to_vec();
590    let mut iv = iv.to_vec();
591    for chunk in output.chunks_mut(16) {
592        let encrypted = chunk.to_vec();
593        match key.len() {
594            16 => {
595                let cipher = Aes128::new_from_slice(key).map_err(|e| {
596                    std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
597                })?;
598                cipher.decrypt_block(GenericArray::from_mut_slice(chunk));
599            }
600            24 => {
601                let cipher = Aes192::new_from_slice(key).map_err(|e| {
602                    std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
603                })?;
604                cipher.decrypt_block(GenericArray::from_mut_slice(chunk));
605            }
606            32 => {
607                let cipher = Aes256::new_from_slice(key).map_err(|e| {
608                    std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{e:?}"))
609                })?;
610                cipher.decrypt_block(GenericArray::from_mut_slice(chunk));
611            }
612            _ => {
613                return Err(Box::new(std::io::Error::new(
614                    std::io::ErrorKind::InvalidData,
615                    "invalid AES key size",
616                )));
617            }
618        }
619        for i in 0..16 {
620            chunk[i] ^= iv[i];
621        }
622        iv = encrypted;
623    }
624    Ok(output)
625}
626
627fn decrypt_package(package_key: &[u8], input: &[u8], encryption: &Encryption) -> Result<Vec<u8>> {
628    let encrypted_key = &encryption.key_data;
629    if input.len() < PACKAGE_OFFSET {
630        return Err(Box::new(ErrWorkbookFileFormat));
631    }
632    let package_size = u64::from_le_bytes([
633        input[0], input[1], input[2], input[3], input[4], input[5], input[6], input[7],
634    ]) as usize;
635    let input = &input[PACKAGE_OFFSET..];
636    let mut output_chunks = Vec::with_capacity(input.len());
637    let mut end = 0;
638    let mut i = 0;
639    while end < input.len() {
640        let start = end;
641        end = (start + PACKAGE_ENCRYPTION_CHUNK_SIZE).min(input.len());
642        let mut input_chunk = input[start..end].to_vec();
643        let remainder = input_chunk.len() % encrypted_key.block_size as usize;
644        if remainder != 0 {
645            input_chunk
646                .extend_from_slice(&vec![0u8; encrypted_key.block_size as usize - remainder]);
647        }
648        let iv = create_iv(i, encryption)?;
649        let output_chunk = decrypt_aes_cbc(package_key, &iv, &input_chunk)?;
650        output_chunks.extend_from_slice(&output_chunk);
651        i += 1;
652    }
653    if output_chunks.len() > package_size {
654        output_chunks.truncate(package_size);
655    }
656    Ok(output_chunks)
657}
658
659fn create_iv(block_key_arg: i32, encryption: &Encryption) -> Result<Vec<u8>> {
660    let encrypted_key = &encryption.key_data;
661    let block_key_buf = create_uint32_le_buffer(block_key_arg, 4);
662    let salt_value = base64_decode(&encrypted_key.salt_value)?;
663    let mut iv = hashing(
664        &encrypted_key.hash_algorithm,
665        &[&salt_value, &block_key_buf],
666    );
667    if iv.len() < encrypted_key.block_size as usize {
668        iv.extend_from_slice(&vec![0x36u8; 0x36]);
669    } else if iv.len() > encrypted_key.block_size as usize {
670        iv.truncate(encrypted_key.block_size as usize);
671    }
672    Ok(iv)
673}
674
675// ------------------------------------------------------------------
676// Hashing & helpers
677// ------------------------------------------------------------------
678
679fn hashing(hash_algorithm: &str, buffers: &[&[u8]]) -> Vec<u8> {
680    use digest::DynDigest;
681    let mut hasher: Box<dyn DynDigest> = match hash_algorithm.to_lowercase().as_str() {
682        "md4" => Box::new(md4::Md4::default()),
683        "md5" => Box::new(md5::Md5::default()),
684        "ripemd-160" => Box::new(ripemd::Ripemd160::default()),
685        "sha1" => Box::new(sha1::Sha1::default()),
686        "sha256" => Box::new(sha2::Sha256::default()),
687        "sha384" => Box::new(sha2::Sha384::default()),
688        "sha512" => Box::new(sha2::Sha512::default()),
689        _ => return Vec::new(),
690    };
691    for buf in buffers {
692        hasher.update(buf);
693    }
694    hasher.finalize_reset().to_vec()
695}
696
697fn create_uint32_le_buffer(value: i32, buffer_size: usize) -> Vec<u8> {
698    let mut buf = vec![0u8; buffer_size];
699    let bytes = (value as u32).to_le_bytes();
700    buf[..4].copy_from_slice(&bytes);
701    buf
702}
703
704fn encode_utf16le(s: &str) -> Vec<u8> {
705    let mut out = Vec::with_capacity(s.len() * 2);
706    for unit in s.encode_utf16() {
707        out.extend_from_slice(&unit.to_le_bytes());
708    }
709    out
710}
711
712fn base64_decode(s: &str) -> Result<Vec<u8>> {
713    Ok(base64::engine::general_purpose::STANDARD.decode(s)?)
714}
715
716fn random_bytes(n: usize) -> Result<Vec<u8>> {
717    let mut buf = vec![0u8; n];
718    rand::thread_rng().fill_bytes(&mut buf);
719    Ok(buf)
720}
721
722// ------------------------------------------------------------------
723// ISO password hashing (sheet / workbook protection)
724// ------------------------------------------------------------------
725
726/// Generate an ISO password hash, salt and hash value.
727pub fn gen_iso_passwd_hash(
728    passwd: &str,
729    hash_algorithm: &str,
730    salt: &str,
731    spin_count: i32,
732) -> Result<(String, String)> {
733    if count_utf16_string(passwd) < 1 || count_utf16_string(passwd) > MAX_FIELD_LENGTH {
734        return Err(Box::new(ErrPasswordLengthInvalid));
735    }
736    let algorithm_name = match hash_algorithm {
737        "MD4" => "md4",
738        "MD5" => "md5",
739        "SHA-1" => "sha1",
740        "SHA-256" => "sha256",
741        "SHA-384" => "sha384",
742        "SHA-512" => "sha512",
743        _ => return Err(Box::new(ErrUnsupportedHashAlgorithm)),
744    };
745    let mut s = random_bytes(16)?;
746    if !salt.is_empty() {
747        s = base64_decode(salt)?;
748    }
749    let mut buffer = Vec::with_capacity(s.len() + passwd.len() * 2);
750    buffer.extend_from_slice(&s);
751    buffer.extend_from_slice(&encode_utf16le(passwd));
752    let mut key = hashing(algorithm_name, &[&buffer]);
753    for i in 0..spin_count {
754        let iterator = create_uint32_le_buffer(i, 4);
755        key = hashing(algorithm_name, &[&key, &iterator]);
756    }
757    Ok((
758        base64::engine::general_purpose::STANDARD.encode(&key),
759        base64::engine::general_purpose::STANDARD.encode(&s),
760    ))
761}
762
763// ------------------------------------------------------------------
764// Byte writer used to build the standard encryption info stream
765// ------------------------------------------------------------------
766
767struct ByteWriter {
768    buf: Vec<u8>,
769}
770
771impl ByteWriter {
772    fn new() -> Self {
773        Self { buf: Vec::new() }
774    }
775
776    fn write_bytes(&mut self, value: &[u8]) {
777        self.buf.extend_from_slice(value);
778    }
779
780    fn write_uint16(&mut self, value: u16) {
781        self.buf.extend_from_slice(&value.to_le_bytes());
782    }
783
784    fn write_uint32(&mut self, value: u32) {
785        self.buf.extend_from_slice(&value.to_le_bytes());
786    }
787
788    fn write_uint64(&mut self, value: u64) {
789        self.buf.extend_from_slice(&value.to_le_bytes());
790    }
791
792    fn write_utf16le(&mut self, value: &str) {
793        self.write_bytes(&encode_utf16le(value));
794    }
795
796    fn into_inner(self) -> Vec<u8> {
797        self.buf
798    }
799}