aescrypt_rs/encryptor/
write.rs

1//! src/encryptor/write.rs
2//! AES Crypt write helpers — FULL secure-gate v0.5.5+ protection
3
4use crate::aliases::HmacSha256;
5use crate::aliases::{Aes256Key, EncryptedSessionBlock48, Iv16, Password, PlainTextBlock16};
6use crate::consts::PBKDF2_MAX_ITER;
7use crate::derive_secure_pbkdf2_key;
8use crate::error::AescryptError;
9use crate::utils::xor_blocks;
10use aes::cipher::BlockEncrypt;
11use aes::{Aes256Enc, Block as AesBlock};
12use hmac::Mac;
13use std::io::Write;
14
15#[inline]
16pub fn write_octets<W: Write>(writer: &mut W, data: &[u8]) -> Result<(), AescryptError> {
17    writer.write_all(data).map_err(AescryptError::Io)
18}
19
20#[inline]
21pub fn write_header<W: Write>(writer: &mut W, version: u8) -> Result<(), AescryptError> {
22    if version < 3 {
23        return Err(AescryptError::UnsupportedVersion(version));
24    }
25    write_octets(writer, &[b'A', b'E', b'S', version, 0x00])
26}
27
28#[inline]
29pub fn write_extensions<W: Write>(
30    writer: &mut W,
31    version: u8,
32    extensions: Option<&[u8]>,
33) -> Result<(), AescryptError> {
34    if version < 3 {
35        return Err(AescryptError::UnsupportedVersion(version));
36    }
37    let data = extensions.unwrap_or(&[0x00, 0x00]);
38    write_octets(writer, data)
39}
40
41#[inline]
42pub fn write_iterations<W: Write>(
43    writer: &mut W,
44    iterations: u32,
45    version: u8,
46) -> Result<(), AescryptError> {
47    if version < 3 {
48        return Err(AescryptError::UnsupportedVersion(version));
49    }
50    if iterations == 0 || iterations > PBKDF2_MAX_ITER {
51        return Err(AescryptError::Header("invalid KDF iterations".into()));
52    }
53    write_octets(writer, &iterations.to_be_bytes())
54}
55
56#[inline]
57pub fn write_public_iv<W: Write>(writer: &mut W, iv: &Iv16) -> Result<(), AescryptError> {
58    write_octets(writer, iv.expose_secret())
59}
60
61#[inline]
62pub fn derive_setup_key(
63    password: &Password,
64    public_iv: &Iv16,
65    iterations: u32,
66    out_key: &mut Aes256Key,
67) -> Result<(), AescryptError> {
68    derive_secure_pbkdf2_key(password, public_iv, iterations, out_key)
69}
70
71#[inline]
72pub fn encrypt_session_block(
73    cipher: &Aes256Enc,
74    session_iv: &Iv16,
75    session_key: &Aes256Key,
76    public_iv: &Iv16,
77    enc_block: &mut EncryptedSessionBlock48,
78    hmac: &mut HmacSha256,
79) -> Result<(), AescryptError> {
80    let mut prev = *public_iv.expose_secret();
81    let mut block = PlainTextBlock16::new([0u8; 16]);
82
83    // Block 1: session IV
84    xor_blocks(session_iv.expose_secret(), &prev, block.expose_secret_mut());
85    let mut aes_block = AesBlock::from(*block.expose_secret());
86    cipher.encrypt_block(&mut aes_block);
87    enc_block.expose_secret_mut()[0..16].copy_from_slice(aes_block.as_ref());
88    hmac.update(&enc_block.expose_secret()[0..16]);
89    prev.copy_from_slice(&enc_block.expose_secret()[0..16]);
90
91    // Block 2: first half of session key
92    xor_blocks(
93        &session_key.expose_secret()[0..16],
94        &prev,
95        block.expose_secret_mut(),
96    );
97    aes_block = AesBlock::from(*block.expose_secret());
98    cipher.encrypt_block(&mut aes_block);
99    enc_block.expose_secret_mut()[16..32].copy_from_slice(aes_block.as_ref());
100    hmac.update(&enc_block.expose_secret()[16..32]);
101    prev.copy_from_slice(&enc_block.expose_secret()[16..32]);
102
103    // Block 3: second half of session key
104    xor_blocks(
105        &session_key.expose_secret()[16..32],
106        &prev,
107        block.expose_secret_mut(),
108    );
109    aes_block = AesBlock::from(*block.expose_secret());
110    cipher.encrypt_block(&mut aes_block);
111    enc_block.expose_secret_mut()[32..48].copy_from_slice(aes_block.as_ref());
112    hmac.update(&enc_block.expose_secret()[32..48]);
113
114    Ok(())
115}
116
117#[inline]
118pub fn write_hmac<W: Write>(writer: &mut W, hmac: HmacSha256) -> Result<(), AescryptError> {
119    write_octets(writer, hmac.finalize().into_bytes().as_slice())
120}