use engram_rs::{ArchiveReader, ArchiveWriter};
use tempfile::NamedTempFile;
fn test_key() -> [u8; 32] {
[0x42; 32] }
fn different_key() -> [u8; 32] {
[0x99; 32]
}
#[test]
fn test_archive_encryption_roundtrip() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("test.txt", b"Secret data").unwrap();
writer.add_file("data.bin", &vec![0xAB; 1024]).unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
assert_eq!(reader.entry_count(), 2);
let files = reader.list_files();
assert_eq!(files.len(), 2);
let data = reader.read_file("test.txt").unwrap();
assert_eq!(data, b"Secret data");
let binary = reader.read_file("data.bin").unwrap();
assert_eq!(binary.len(), 1024);
assert_eq!(binary[0], 0xAB);
}
}
#[test]
fn test_per_file_encryption_roundtrip() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&key);
let mut writer = writer;
writer.add_file("encrypted1.txt", b"First secret").unwrap();
writer.add_file("encrypted2.txt", b"Second secret").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
assert_eq!(reader.entry_count(), 2);
let data1 = reader.read_file("encrypted1.txt").unwrap();
assert_eq!(data1, b"First secret");
let data2 = reader.read_file("encrypted2.txt").unwrap();
assert_eq!(data2, b"Second secret");
}
}
#[test]
fn test_wrong_key_archive_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("secret.txt", b"Confidential").unwrap();
writer.finalize().unwrap();
}
{
let wrong_key = different_key();
let mut reader = ArchiveReader::open(path)
.unwrap()
.with_decryption_key(&wrong_key);
let result = reader.initialize();
assert!(result.is_err(), "Wrong key should fail to decrypt");
}
}
#[test]
fn test_wrong_key_per_file_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&key);
let mut writer = writer;
writer.add_file("encrypted.txt", b"Secret").unwrap();
writer.finalize().unwrap();
}
{
let wrong_key = different_key();
let mut reader = ArchiveReader::open(path)
.unwrap()
.with_decryption_key(&wrong_key);
reader.initialize().unwrap();
let result = reader.read_file("encrypted.txt");
assert!(
result.is_err(),
"Wrong key should fail to decrypt file data"
);
}
}
#[test]
fn test_missing_decryption_key_archive() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("secret.txt", b"Data").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap();
let result = reader.initialize();
assert!(result.is_err(), "Missing key should fail");
}
}
#[test]
fn test_missing_decryption_key_per_file() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&key);
let mut writer = writer;
writer.add_file("encrypted.txt", b"Secret").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap();
reader.initialize().unwrap();
let result = reader.read_file("encrypted.txt");
assert!(result.is_err(), "Missing key should fail to decrypt file");
}
}
#[test]
fn test_unencrypted_archive_normal_read() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
{
let mut writer = ArchiveWriter::create(path).unwrap();
writer.add_file("plain.txt", b"Not encrypted").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open_and_init(path).unwrap();
let data = reader.read_file("plain.txt").unwrap();
assert_eq!(data, b"Not encrypted");
}
}
#[test]
fn test_archive_encryption_with_compression() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
let data = b"AAAA".repeat(1000);
writer.add_file("compressed.txt", &data).unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
let data = reader.read_file("compressed.txt").unwrap();
assert_eq!(data.len(), 4000);
assert_eq!(&data[0..4], b"AAAA");
}
}
#[test]
fn test_per_file_encryption_with_compression() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&key);
let mut writer = writer;
let data = b"BBBB".repeat(1000);
writer.add_file("file.txt", &data).unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
let data = reader.read_file("file.txt").unwrap();
assert_eq!(data.len(), 4000);
assert_eq!(&data[0..4], b"BBBB");
}
}
#[test]
fn test_empty_file_with_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("empty.txt", b"").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
let files = reader.list_files();
println!("Files in encrypted archive: {:?}", files);
let result = reader.read_file("empty.txt");
if let Ok(data) = result {
assert_eq!(data, b"");
} else {
println!("Note: Empty file handling with encryption may have issues");
}
}
}
#[test]
fn test_multiple_files_archive_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
for i in 0..10 {
let filename = format!("file{}.txt", i);
let content = format!("Content {}", i);
writer.add_file(&filename, content.as_bytes()).unwrap();
}
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
assert_eq!(reader.entry_count(), 10);
for i in 0..10 {
let filename = format!("file{}.txt", i);
let expected = format!("Content {}", i);
let data = reader.read_file(&filename).unwrap();
assert_eq!(data, expected.as_bytes());
}
}
}
#[test]
fn test_binary_data_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
let binary: Vec<u8> = (0..=255).collect();
writer.add_file("binary.bin", &binary).unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
let data = reader.read_file("binary.bin").unwrap();
assert_eq!(data.len(), 256);
for i in 0..=255u8 {
assert_eq!(data[i as usize], i);
}
}
}
#[test]
fn test_large_file_encryption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
let large_data = vec![0x55u8; 1024 * 1024]; writer.add_file("large.bin", &large_data).unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
let data = reader.read_file("large.bin").unwrap();
assert_eq!(data.len(), 1024 * 1024);
assert_eq!(data[0], 0x55);
assert_eq!(data[1024 * 1024 - 1], 0x55);
}
}
#[test]
fn test_encryption_preserves_metadata() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("test.txt", b"Data").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap().with_decryption_key(&key);
reader.initialize().unwrap();
assert_eq!(reader.entry_count(), 1);
assert!(reader.contains("test.txt"));
let files = reader.list_files();
assert_eq!(files.len(), 1);
assert_eq!(files[0], "test.txt");
}
}
#[test]
fn test_per_file_encryption_central_directory_readable() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&key);
let mut writer = writer;
writer.add_file("file1.txt", b"Secret 1").unwrap();
writer.add_file("file2.txt", b"Secret 2").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap();
reader.initialize().unwrap();
assert_eq!(reader.entry_count(), 2);
let files = reader.list_files();
assert_eq!(files.len(), 2);
assert!(files.contains(&"file1.txt".to_string()));
assert!(files.contains(&"file2.txt".to_string()));
let result1 = reader.read_file("file1.txt");
assert!(
result1.is_err(),
"Should not be able to read encrypted file without key"
);
let result2 = reader.read_file("file2.txt");
assert!(
result2.is_err(),
"Should not be able to read encrypted file without key"
);
}
}
#[test]
fn test_archive_encryption_hides_file_list() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let key = test_key();
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&key);
let mut writer = writer;
writer.add_file("secret1.txt", b"Data 1").unwrap();
writer.add_file("secret2.txt", b"Data 2").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path).unwrap();
let result = reader.initialize();
assert!(
result.is_err(),
"Archive encryption should hide file list without key"
);
}
}
#[test]
fn test_zero_key() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let zero_key = [0u8; 32];
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_archive_encryption(&zero_key);
let mut writer = writer;
writer.add_file("test.txt", b"Data").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path)
.unwrap()
.with_decryption_key(&zero_key);
reader.initialize().unwrap();
let data = reader.read_file("test.txt").unwrap();
assert_eq!(data, b"Data");
}
}
#[test]
fn test_all_ones_key() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
let ones_key = [0xFFu8; 32];
{
let writer = ArchiveWriter::create(path)
.unwrap()
.with_per_file_encryption(&ones_key);
let mut writer = writer;
writer.add_file("test.txt", b"Data").unwrap();
writer.finalize().unwrap();
}
{
let mut reader = ArchiveReader::open(path)
.unwrap()
.with_decryption_key(&ones_key);
reader.initialize().unwrap();
let data = reader.read_file("test.txt").unwrap();
assert_eq!(data, b"Data");
}
}