Skip to content

stream, aes-gcm: Decryption fails on some files #813

@schn4v1d

Description

@schn4v1d

Hi! I am using aes-gcm and aead::stream to encrypt and decrypt in a file storage solution.

I am encountering a problem where some files are encrypted successfully but consistently cause an error on the Decryptor::decrypt_last function when decrypted, while others work flawlessly. I am unable to share the files but one that works is 10,212,932 Bytes and the one that produces the error is 10,027,738 Bytes.

As the error type is 100% opaque, I am not quite sure where to even start debugging if this is an internal library error or misuse on my part. I'll appreciate any help or guidance with this issue.

This is a simplified version of my decrypt function:

const ENCRYPT_BUFFER_LEN: usize = 1024;
const DECRYPT_BUFFER_LEN: usize = ENCRYPT_BUFFER_LEN + 16;

pub async fn decrypt<I: AsyncRead + Unpin>(
    key: &Key,
    input: &mut I,
) -> std::result::Result<File, DecryptError> {
    let mut output = File::from_std(tempfile().unwrap());

    let mut nonce = [0; 7];
    input
        .read_exact(&mut nonce)
        .await.unwrap();

    let mut decryptor = DecryptorBE32::<Aes256Gcm>::new(key, &nonce.into());

    let mut buffer = BytesMut::zeroed(DECRYPT_BUFFER_LEN);

    loop {
        let mut position = 0;

        // read until buffer full or eof
        while position < DECRYPT_BUFFER_LEN {
            let read = input
                .read(&mut buffer[position..])
                .await
                .unwrap();

            if read == 0 {
                break;
            }

            position += read;
        }

        if position == 0 {
            break;
        } else if position == DECRYPT_BUFFER_LEN {
            let ciphertext = decryptor.decrypt_next(&buffer[..])?;

            output
                .write_all(&ciphertext)
                .await
                .unwrap();
        } else {
            let ciphertext = decryptor.decrypt_last(&buffer[0..position])?;

            output
                .write_all(&ciphertext)
                .await
                .unwrap();

            break;
        }
    }

    output.flush().await.unwrap();

    output
        .seek(SeekFrom::Start(0))
        .await
        .unwrap();

    Ok(output)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions