use crate::encryption::{CryptFilterMethod, EncryptionKey, Permissions, SecurityHandler};
use crate::error::{PdfError, Result};
use crate::objects::{Dictionary, Object, ObjectId};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum SubFilter {
AdbePkcs7S3,
AdbePkcs7S4,
AdbePkcs7S5,
AdbeX509RsaSha1,
Custom(String),
}
impl SubFilter {
pub fn to_name(&self) -> &str {
match self {
SubFilter::AdbePkcs7S3 => "adbe.pkcs7.s3",
SubFilter::AdbePkcs7S4 => "adbe.pkcs7.s4",
SubFilter::AdbePkcs7S5 => "adbe.pkcs7.s5",
SubFilter::AdbeX509RsaSha1 => "adbe.x509.rsa_sha1",
SubFilter::Custom(name) => name,
}
}
pub fn from_name(name: &str) -> Self {
match name {
"adbe.pkcs7.s3" => SubFilter::AdbePkcs7S3,
"adbe.pkcs7.s4" => SubFilter::AdbePkcs7S4,
"adbe.pkcs7.s5" => SubFilter::AdbePkcs7S5,
"adbe.x509.rsa_sha1" => SubFilter::AdbeX509RsaSha1,
_ => SubFilter::Custom(name.to_string()),
}
}
}
#[derive(Debug, Clone)]
pub struct Recipient {
pub certificate: Vec<u8>,
pub permissions: Permissions,
pub encrypted_seed: Vec<u8>,
}
pub struct PublicKeySecurityHandler {
pub subfilter: SubFilter,
pub recipients: Vec<Recipient>,
pub seed_length: usize,
pub method: CryptFilterMethod,
}
impl PublicKeySecurityHandler {
pub fn new_sha1() -> Self {
Self {
subfilter: SubFilter::AdbePkcs7S3,
recipients: Vec::new(),
seed_length: 20,
method: CryptFilterMethod::V2,
}
}
pub fn new_sha256() -> Self {
Self {
subfilter: SubFilter::AdbePkcs7S4,
recipients: Vec::new(),
seed_length: 32,
method: CryptFilterMethod::AESV2,
}
}
pub fn add_recipient(
&mut self,
_certificate: Vec<u8>,
_permissions: Permissions,
) -> Result<()> {
Err(unsupported_recipient_encryption())
}
pub fn decrypt_seed(&self, _encrypted_seed: &[u8], _private_key: &[u8]) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
pub fn build_recipients_dict(&self) -> Dictionary {
let mut dict = Dictionary::new();
let recipients_array: Vec<Object> = self
.recipients
.iter()
.map(|recipient| {
let mut recipient_dict = Dictionary::new();
recipient_dict.set(
"Cert",
Object::String(String::from_utf8_lossy(&recipient.certificate).to_string()),
);
recipient_dict.set("P", Object::Integer(recipient.permissions.bits() as i64));
recipient_dict.set(
"Recipients",
Object::String(String::from_utf8_lossy(&recipient.encrypted_seed).to_string()),
);
Object::Dictionary(recipient_dict)
})
.collect();
dict.set("Recipients", Object::Array(recipients_array));
dict
}
pub fn verify_permission(&self, _recipient_index: usize, _permission: Permissions) -> bool {
false
}
}
fn unsupported_recipient_encryption() -> PdfError {
PdfError::EncryptionError("Certificate-based recipient encryption is not supported".to_string())
}
impl SecurityHandler for PublicKeySecurityHandler {
fn encrypt_string(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn decrypt_string(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn encrypt_stream(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn decrypt_stream(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn encrypt_string_aes(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
_bits: u32,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn decrypt_string_aes(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
_bits: u32,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn encrypt_stream_aes(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
_bits: u32,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
fn decrypt_stream_aes(
&self,
_data: &[u8],
_encryption_key: &EncryptionKey,
_obj_id: &ObjectId,
_bits: u32,
) -> Result<Vec<u8>> {
Err(unsupported_recipient_encryption())
}
}
#[derive(Debug, Clone)]
pub struct PublicKeyEncryptionDict {
pub filter: String,
pub subfilter: SubFilter,
pub v: u8,
pub length: Option<u32>,
pub cf: Option<HashMap<String, Dictionary>>,
pub stm_f: Option<String>,
pub str_f: Option<String>,
pub recipients: Vec<Dictionary>,
pub encrypt_metadata: bool,
}
impl PublicKeyEncryptionDict {
pub fn new(handler: &PublicKeySecurityHandler) -> Self {
Self {
filter: "Adobe.PubSec".to_string(),
subfilter: handler.subfilter.clone(),
v: match handler.method {
CryptFilterMethod::V2 => 2,
CryptFilterMethod::AESV2 => 4,
CryptFilterMethod::AESV3 => 5,
_ => 4,
},
length: Some(match handler.method {
CryptFilterMethod::V2 => 128,
_ => 256,
}),
cf: None,
stm_f: Some("DefaultCryptFilter".to_string()),
str_f: Some("DefaultCryptFilter".to_string()),
recipients: handler
.recipients
.iter()
.map(|r| {
let mut dict = Dictionary::new();
dict.set(
"Cert",
Object::String(String::from_utf8_lossy(&r.certificate).to_string()),
);
dict.set("P", Object::Integer(r.permissions.bits() as i64));
dict.set(
"Recipients",
Object::String(String::from_utf8_lossy(&r.encrypted_seed).to_string()),
);
dict
})
.collect(),
encrypt_metadata: true,
}
}
pub fn to_dict(&self) -> Dictionary {
let mut dict = Dictionary::new();
dict.set("Filter", Object::Name(self.filter.clone()));
dict.set(
"SubFilter",
Object::Name(self.subfilter.to_name().to_string()),
);
dict.set("V", Object::Integer(self.v as i64));
if let Some(length) = self.length {
dict.set("Length", Object::Integer(length as i64));
}
if let Some(ref _cf) = self.cf {
let cf_dict = Dictionary::new();
dict.set("CF", Object::Dictionary(cf_dict));
}
if let Some(ref stm_f) = self.stm_f {
dict.set("StmF", Object::Name(stm_f.clone()));
}
if let Some(ref str_f) = self.str_f {
dict.set("StrF", Object::Name(str_f.clone()));
}
let recipients_array: Vec<Object> = self
.recipients
.iter()
.map(|r| Object::Dictionary(r.clone()))
.collect();
dict.set("Recipients", Object::Array(recipients_array));
dict.set("EncryptMetadata", Object::Boolean(self.encrypt_metadata));
dict
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_subfilter_conversion() {
assert_eq!(SubFilter::AdbePkcs7S3.to_name(), "adbe.pkcs7.s3");
assert_eq!(SubFilter::AdbePkcs7S4.to_name(), "adbe.pkcs7.s4");
assert_eq!(SubFilter::AdbePkcs7S5.to_name(), "adbe.pkcs7.s5");
assert_eq!(SubFilter::AdbeX509RsaSha1.to_name(), "adbe.x509.rsa_sha1");
let custom = SubFilter::Custom("custom.filter".to_string());
assert_eq!(custom.to_name(), "custom.filter");
}
#[test]
fn test_subfilter_from_name() {
assert_eq!(
SubFilter::from_name("adbe.pkcs7.s3"),
SubFilter::AdbePkcs7S3
);
assert_eq!(
SubFilter::from_name("adbe.pkcs7.s4"),
SubFilter::AdbePkcs7S4
);
assert_eq!(
SubFilter::from_name("adbe.pkcs7.s5"),
SubFilter::AdbePkcs7S5
);
assert_eq!(
SubFilter::from_name("adbe.x509.rsa_sha1"),
SubFilter::AdbeX509RsaSha1
);
assert_eq!(
SubFilter::from_name("unknown"),
SubFilter::Custom("unknown".to_string())
);
}
#[test]
fn test_public_key_handler_creation() {
let handler_sha1 = PublicKeySecurityHandler::new_sha1();
assert_eq!(handler_sha1.subfilter, SubFilter::AdbePkcs7S3);
assert_eq!(handler_sha1.seed_length, 20);
assert_eq!(handler_sha1.method, CryptFilterMethod::V2);
let handler_sha256 = PublicKeySecurityHandler::new_sha256();
assert_eq!(handler_sha256.subfilter, SubFilter::AdbePkcs7S4);
assert_eq!(handler_sha256.seed_length, 32);
assert_eq!(handler_sha256.method, CryptFilterMethod::AESV2);
}
}