use oxidize_pdf::encryption::{
EncryptionKey, OwnerPassword, Permissions, StandardSecurityHandler, UserPassword,
};
#[test]
fn test_compute_encryption_key_rc4_40bit() {
let handler = StandardSecurityHandler::rc4_40bit();
let user_pwd = UserPassword("test".to_string());
let owner_hash = vec![0xAA; 32];
let permissions = Permissions::new();
let file_id = b"test_file_id_123";
let result = handler.compute_encryption_key(&user_pwd, &owner_hash, permissions, Some(file_id));
assert!(result.is_ok(), "Encryption key computation should succeed");
let key = result.unwrap();
assert_eq!(key.len(), 5, "RC4 40-bit key should be 5 bytes");
}
#[test]
fn test_compute_encryption_key_rc4_128bit() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("password123".to_string());
let owner_hash = vec![0xBB; 32];
let permissions = Permissions::all();
let file_id = b"document_id_456";
let result = handler.compute_encryption_key(&user_pwd, &owner_hash, permissions, Some(file_id));
assert!(result.is_ok(), "Encryption key computation should succeed");
let key = result.unwrap();
assert_eq!(key.len(), 16, "RC4 128-bit key should be 16 bytes");
}
#[test]
fn test_compute_encryption_key_deterministic() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("same_password".to_string());
let owner_hash = vec![0xCC; 32];
let permissions = Permissions::new();
let file_id = b"same_file_id";
let key1 = handler
.compute_encryption_key(&user_pwd, &owner_hash, permissions, Some(file_id))
.unwrap();
let key2 = handler
.compute_encryption_key(&user_pwd, &owner_hash, permissions, Some(file_id))
.unwrap();
assert_eq!(
key1.as_bytes(),
key2.as_bytes(),
"Same inputs should produce same encryption key"
);
}
#[test]
fn test_compute_encryption_key_different_passwords() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd1 = UserPassword("password1".to_string());
let user_pwd2 = UserPassword("password2".to_string());
let owner_hash = vec![0xDD; 32];
let permissions = Permissions::new();
let file_id = b"file_id";
let key1 = handler
.compute_encryption_key(&user_pwd1, &owner_hash, permissions, Some(file_id))
.unwrap();
let key2 = handler
.compute_encryption_key(&user_pwd2, &owner_hash, permissions, Some(file_id))
.unwrap();
assert_ne!(
key1.as_bytes(),
key2.as_bytes(),
"Different passwords should produce different keys"
);
}
#[test]
fn test_validate_user_password_correct_r2() {
let handler = StandardSecurityHandler::rc4_40bit();
let user_pwd = UserPassword("correct".to_string());
let owner_hash = vec![0xEE; 32];
let permissions = Permissions::new();
let file_id = b"test_id";
let user_hash = handler
.compute_user_hash(&user_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&user_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(
result.is_ok(),
"Password validation should not return error"
);
assert!(
result.unwrap(),
"Correct password should validate successfully"
);
}
#[test]
fn test_validate_user_password_incorrect_r2() {
let handler = StandardSecurityHandler::rc4_40bit();
let correct_pwd = UserPassword("correct".to_string());
let wrong_pwd = UserPassword("wrong".to_string());
let owner_hash = vec![0xFF; 32];
let permissions = Permissions::new();
let file_id = b"test_id";
let user_hash = handler
.compute_user_hash(&correct_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&wrong_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(
result.is_ok(),
"Password validation should not return error for wrong password"
);
assert!(
!result.unwrap(),
"Wrong password should not validate successfully"
);
}
#[test]
fn test_validate_user_password_correct_r3() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("mypassword".to_string());
let owner_hash = vec![0x11; 32];
let permissions = Permissions::all();
let file_id = b"doc_id_r3";
let user_hash = handler
.compute_user_hash(&user_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&user_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(
result.is_ok(),
"Password validation should not return error"
);
assert!(
result.unwrap(),
"Correct password should validate successfully"
);
}
#[test]
fn test_validate_user_password_incorrect_r3() {
let handler = StandardSecurityHandler::rc4_128bit();
let correct_pwd = UserPassword("correct_r3".to_string());
let wrong_pwd = UserPassword("wrong_r3".to_string());
let owner_hash = vec![0x22; 32];
let permissions = Permissions::new();
let file_id = b"doc_id_r3";
let user_hash = handler
.compute_user_hash(&correct_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&wrong_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(
result.is_ok(),
"Password validation should not return error for wrong password"
);
assert!(
!result.unwrap(),
"Wrong password should not validate successfully"
);
}
#[test]
fn test_validate_empty_user_password() {
let handler = StandardSecurityHandler::rc4_128bit();
let empty_pwd = UserPassword("".to_string());
let owner_hash = vec![0x33; 32];
let permissions = Permissions::new();
let file_id = b"empty_pwd_doc";
let user_hash = handler
.compute_user_hash(&empty_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&empty_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(
result.is_ok(),
"Empty password validation should not return error"
);
assert!(
result.unwrap(),
"Empty password should validate successfully when document uses empty password"
);
}
#[test]
fn test_validate_owner_password_correct() {
let handler = StandardSecurityHandler::rc4_128bit();
let owner_pwd = OwnerPassword("owner_secret".to_string());
let user_pwd = UserPassword("user123".to_string());
let permissions = Permissions::new();
let file_id = b"owner_test_id";
let owner_hash = handler.compute_owner_hash(&owner_pwd, &user_pwd);
let result = handler.validate_owner_password(
&owner_pwd,
&owner_hash,
&user_pwd,
permissions,
Some(file_id),
None, );
assert!(
result.is_ok(),
"Owner password validation should not return error"
);
assert!(
result.unwrap(),
"Correct owner password should validate successfully"
);
}
#[test]
fn test_validate_owner_password_incorrect() {
let handler = StandardSecurityHandler::rc4_128bit();
let correct_owner = OwnerPassword("correct_owner".to_string());
let wrong_owner = OwnerPassword("wrong_owner".to_string());
let user_pwd = UserPassword("user456".to_string());
let permissions = Permissions::new();
let file_id = b"owner_test_id2";
let owner_hash = handler.compute_owner_hash(&correct_owner, &user_pwd);
let result = handler.validate_owner_password(
&wrong_owner,
&owner_hash,
&user_pwd,
permissions,
Some(file_id),
None, );
assert!(
result.is_ok(),
"Owner password validation should not return error for wrong password"
);
assert!(
!result.unwrap(),
"Wrong owner password should not validate successfully"
);
}
#[test]
fn test_validate_password_no_file_id() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("test".to_string());
let owner_hash = vec![0x44; 32];
let permissions = Permissions::new();
let user_hash = handler
.compute_user_hash(&user_pwd, &owner_hash, permissions, None)
.expect("User hash computation without file_id should succeed");
let result =
handler.validate_user_password(&user_pwd, &user_hash, &owner_hash, permissions, None);
assert!(result.is_ok(), "Validation without file_id should work");
assert!(
result.unwrap(),
"Password should validate even without file_id"
);
}
#[test]
fn test_validate_password_with_all_permissions() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("all_perms".to_string());
let owner_hash = vec![0x55; 32];
let permissions = Permissions::all();
let file_id = b"all_perms_id";
let user_hash = handler
.compute_user_hash(&user_pwd, &owner_hash, permissions, Some(file_id))
.expect("User hash computation should succeed");
let result = handler.validate_user_password(
&user_pwd,
&user_hash,
&owner_hash,
permissions,
Some(file_id),
);
assert!(result.is_ok());
assert!(result.unwrap(), "Should validate with all permissions");
}
#[test]
fn test_validate_password_different_permissions() {
let handler = StandardSecurityHandler::rc4_128bit();
let user_pwd = UserPassword("same_pwd".to_string());
let owner_hash = vec![0x66; 32];
let file_id = b"perms_test";
let perms1 = Permissions::new();
let perms2 = Permissions::all();
let user_hash1 = handler
.compute_user_hash(&user_pwd, &owner_hash, perms1, Some(file_id))
.unwrap();
let user_hash2 = handler
.compute_user_hash(&user_pwd, &owner_hash, perms2, Some(file_id))
.unwrap();
assert_ne!(
user_hash1, user_hash2,
"Different permissions should produce different user hashes"
);
}
#[test]
fn test_encryption_key_is_cloneable() {
let key = EncryptionKey::new(vec![1, 2, 3, 4, 5]);
let cloned = key.clone();
assert_eq!(key.as_bytes(), cloned.as_bytes());
assert_eq!(key.len(), cloned.len());
}
#[test]
fn test_password_structs_are_cloneable() {
let user = UserPassword("user".to_string());
let owner = OwnerPassword("owner".to_string());
let user_clone = user.clone();
let owner_clone = owner.clone();
assert_eq!(user.0, user_clone.0);
assert_eq!(owner.0, owner_clone.0);
}
#[test]
fn test_validate_owner_password_r5_correct() {
let handler = StandardSecurityHandler::aes_256_r5();
let owner_pwd = OwnerPassword("r5_owner_secret".to_string());
let user_pwd = UserPassword("".to_string());
let o_entry = handler
.compute_r5_owner_hash(&owner_pwd, &user_pwd)
.expect("R5 owner hash computation should succeed");
let permissions = Permissions::new();
let result = handler.validate_owner_password(
&owner_pwd,
&o_entry,
&user_pwd,
permissions,
None,
None, );
assert!(
result.is_ok(),
"R5 owner password validation should not error: {:?}",
result.err()
);
assert!(
result.unwrap(),
"Correct R5 owner password should validate successfully"
);
}
#[test]
fn test_validate_owner_password_r5_incorrect() {
let handler = StandardSecurityHandler::aes_256_r5();
let correct_owner = OwnerPassword("correct_r5_owner".to_string());
let wrong_owner = OwnerPassword("wrong_r5_owner".to_string());
let user_pwd = UserPassword("".to_string());
let o_entry = handler
.compute_r5_owner_hash(&correct_owner, &user_pwd)
.expect("R5 owner hash computation should succeed");
let permissions = Permissions::new();
let result = handler.validate_owner_password(
&wrong_owner,
&o_entry,
&user_pwd,
permissions,
None,
None, );
assert!(
result.is_ok(),
"R5 owner password validation should not error for wrong password"
);
assert!(
!result.unwrap(),
"Wrong R5 owner password should not validate successfully"
);
}
#[test]
fn test_validate_owner_password_r6_correct() {
let handler = StandardSecurityHandler::aes_256_r6();
let owner_pwd = OwnerPassword("r6_owner_secret".to_string());
let user_pwd = UserPassword("r6_user".to_string());
let u_entry = handler
.compute_r6_user_hash(&user_pwd)
.expect("R6 user hash computation should succeed");
let o_entry = handler
.compute_r6_owner_hash(&owner_pwd, &u_entry)
.expect("R6 owner hash computation should succeed");
let permissions = Permissions::new();
let result = handler.validate_owner_password(
&owner_pwd,
&o_entry,
&user_pwd,
permissions,
None,
Some(&u_entry), );
assert!(
result.is_ok(),
"R6 owner password validation should not error: {:?}",
result.err()
);
assert!(
result.unwrap(),
"Correct R6 owner password should validate successfully"
);
}
#[test]
fn test_validate_owner_password_r6_incorrect() {
let handler = StandardSecurityHandler::aes_256_r6();
let correct_owner = OwnerPassword("correct_r6_owner".to_string());
let wrong_owner = OwnerPassword("wrong_r6_owner".to_string());
let user_pwd = UserPassword("r6_user".to_string());
let u_entry = handler
.compute_r6_user_hash(&user_pwd)
.expect("R6 user hash computation should succeed");
let o_entry = handler
.compute_r6_owner_hash(&correct_owner, &u_entry)
.expect("R6 owner hash computation should succeed");
let permissions = Permissions::new();
let result = handler.validate_owner_password(
&wrong_owner,
&o_entry,
&user_pwd,
permissions,
None,
Some(&u_entry),
);
assert!(
result.is_ok(),
"R6 owner password validation should not error for wrong password"
);
assert!(
!result.unwrap(),
"Wrong R6 owner password should not validate successfully"
);
}
#[test]
fn test_validate_owner_password_r6_missing_u_entry() {
let handler = StandardSecurityHandler::aes_256_r6();
let owner_pwd = OwnerPassword("r6_owner".to_string());
let user_pwd = UserPassword("r6_user".to_string());
let o_entry = vec![0u8; 48];
let permissions = Permissions::new();
let result = handler.validate_owner_password(
&owner_pwd,
&o_entry,
&user_pwd,
permissions,
None,
None, );
assert!(result.is_err(), "R6 should error when U entry is missing");
let err_msg = result.unwrap_err().to_string();
assert!(
err_msg.contains("U entry"),
"Error should mention U entry: {}",
err_msg
);
}
#[test]
fn test_validate_owner_password_r6_invalid_u_entry_length() {
let handler = StandardSecurityHandler::aes_256_r6();
let owner_pwd = OwnerPassword("r6_owner".to_string());
let user_pwd = UserPassword("r6_user".to_string());
let o_entry = vec![0u8; 48];
let invalid_u_entry = vec![0u8; 32]; let permissions = Permissions::new();
let result = handler.validate_owner_password(
&owner_pwd,
&o_entry,
&user_pwd,
permissions,
None,
Some(&invalid_u_entry),
);
assert!(
result.is_err(),
"R6 should error when U entry has invalid length"
);
let err_msg = result.unwrap_err().to_string();
assert!(
err_msg.contains("48 bytes"),
"Error should mention expected length: {}",
err_msg
);
}