zip-rs-wasm/tests/aes_encryption.rs
Johannes Löthberg d096e4dbf1
Add support for writing AES-encrypted files
Signed-off-by: Johannes Löthberg <johannes.loethberg@elokon.com>
2024-05-06 16:37:05 +02:00

154 lines
5 KiB
Rust

#![cfg(feature = "aes-crypto")]
use std::io::{self, Read, Write};
use zip::{result::ZipError, write::SimpleFileOptions, AesMode, CompressionMethod, ZipArchive};
const SECRET_CONTENT: &str = "Lorem ipsum dolor sit amet";
const PASSWORD: &[u8] = b"helloworld";
#[test]
fn aes256_encrypted_uncompressed_file() {
let mut v = Vec::new();
v.extend_from_slice(include_bytes!("data/aes_archive.zip"));
let mut archive = ZipArchive::new(io::Cursor::new(v)).expect("couldn't open test zip file");
let mut file = archive
.by_name_decrypt("secret_data_256_uncompressed", PASSWORD)
.expect("couldn't find file in archive");
assert_eq!("secret_data_256_uncompressed", file.name());
let mut content = String::new();
file.read_to_string(&mut content)
.expect("couldn't read encrypted file");
assert_eq!(SECRET_CONTENT, content);
}
#[test]
fn aes256_encrypted_file() {
let mut v = Vec::new();
v.extend_from_slice(include_bytes!("data/aes_archive.zip"));
let mut archive = ZipArchive::new(io::Cursor::new(v)).expect("couldn't open test zip file");
let mut file = archive
.by_name_decrypt("secret_data_256", PASSWORD)
.expect("couldn't find file in archive");
assert_eq!("secret_data_256", file.name());
let mut content = String::new();
file.read_to_string(&mut content)
.expect("couldn't read encrypted and compressed file");
assert_eq!(SECRET_CONTENT, content);
}
#[test]
fn aes192_encrypted_file() {
let mut v = Vec::new();
v.extend_from_slice(include_bytes!("data/aes_archive.zip"));
let mut archive = ZipArchive::new(io::Cursor::new(v)).expect("couldn't open test zip file");
let mut file = archive
.by_name_decrypt("secret_data_192", PASSWORD)
.expect("couldn't find file in archive");
assert_eq!("secret_data_192", file.name());
let mut content = String::new();
file.read_to_string(&mut content)
.expect("couldn't read encrypted file");
assert_eq!(SECRET_CONTENT, content);
}
#[test]
fn aes128_encrypted_file() {
let mut v = Vec::new();
v.extend_from_slice(include_bytes!("data/aes_archive.zip"));
let mut archive = ZipArchive::new(io::Cursor::new(v)).expect("couldn't open test zip file");
let mut file = archive
.by_name_decrypt("secret_data_128", PASSWORD)
.expect("couldn't find file in archive");
assert_eq!("secret_data_128", file.name());
let mut content = String::new();
file.read_to_string(&mut content)
.expect("couldn't read encrypted file");
assert_eq!(SECRET_CONTENT, content);
}
#[test]
fn aes128_stored_roundtrip() {
let cursor = {
let mut zip = zip::ZipWriter::new(io::Cursor::new(Vec::new()));
zip.start_file(
"test.txt",
SimpleFileOptions::default().with_aes_encryption(AesMode::Aes128, "some password"),
)
.unwrap();
zip.write_all(SECRET_CONTENT.as_bytes()).unwrap();
zip.finish().unwrap()
};
let mut archive = ZipArchive::new(cursor).expect("couldn't open test zip file");
test_extract_encrypted_file(&mut archive, "test.txt", "some password", "other password");
}
#[test]
fn aes256_deflated_roundtrip() {
let cursor = {
let mut zip = zip::ZipWriter::new(io::Cursor::new(Vec::new()));
zip.start_file(
"test.txt",
SimpleFileOptions::default()
.compression_method(CompressionMethod::Deflated)
.with_aes_encryption(AesMode::Aes256, "some password"),
)
.unwrap();
zip.write_all(SECRET_CONTENT.as_bytes()).unwrap();
zip.finish().unwrap()
};
let mut archive = ZipArchive::new(cursor).expect("couldn't open test zip file");
test_extract_encrypted_file(&mut archive, "test.txt", "some password", "other password");
}
fn test_extract_encrypted_file<R: io::Read + io::Seek>(
archive: &mut ZipArchive<R>,
file_name: &str,
correct_password: &str,
incorrect_password: &str,
) {
{
let file = archive.by_name(file_name).map(|_| ());
match file {
Err(ZipError::UnsupportedArchive("Password required to decrypt file")) => {}
Err(err) => {
panic!("Failed to read file for unknown reason: {err:?}");
}
Ok(_) => {
panic!("Was able to successfully read encrypted file without password");
}
}
}
{
match archive.by_name_decrypt(file_name, incorrect_password.as_bytes()) {
Err(ZipError::InvalidPassword) => {}
Err(err) => panic!("Expected invalid password error, got: {err:?}"),
Ok(_) => panic!("Expected invalid password, got decrypted file"),
}
}
{
let mut content = String::new();
archive
.by_name_decrypt(file_name, correct_password.as_bytes())
.expect("couldn't read encrypted file")
.read_to_string(&mut content)
.expect("couldn't read encrypted file");
assert_eq!(SECRET_CONTENT, content);
}
}