Bir izin bayrağı bir güvenlik mekanizması değildir. "Kopyalama yok" diyen bit, kriptografiyle aynı /Encrypt sözlüğü içinde yaşar, bu da ona sahip olmadığı bir uygulanabilirlik havası verir ve ikisini tek bir şeymiş gibi ele aldığınız an denetiminiz yanlış cevaplar üretmeye başlar. Bir PDF'e sorulmaya değer tek soru "şifrelenmiş mi" değildir. Daha spesifik ve daha zor bir sorudur: hangi algoritma, hangi güvenlik işleyici revizyonu, iki paroladan hangisi ayarlanmış, hangi izin bitleri iddia ediliyor ve şifreleme dosyanın gerçekte hangi bölümlerine dokunuyor. Bir dosya resmi olarak şifrelenmiş ve pratikte açık olabilir. Okunmayı reddedebilir ama meta verisini düz metin halinde bırakabilir. Yazdırmayı, herhangi bir görüntüleyicinin görmezden gelmekte özgür olduğu bir bayrakla kilitleyebilir. Bir PDF'i denetlemek, tüm bunları ayrı ayrı çözmek anlamına gelir ve losLab'ın Delphi ve C++Builder için PDF motoru olan PDF Library for Delphi, her birini hem düz bir tam sayı tutamaç API'si hem de tipli bir sınıf katmanı üzerinden sunar
/Encrypt sözlüğünün gerçekte kaydettikleri
ISO 32000-1 §7.6, belge güvenliğini bir avuç sözlük girdisi aracılığıyla tanımlar ve PDF Library for Delphi bunları TPDFEncryption kaydında birebir yansıtır. Filtre sürümü V ve revizyon R, algoritma ailesini seçer. Length anahtar boyutunu taşır. İzin bitleri P'de, sahip ve kullanıcı parola doğrulama dizeleri ise O ve U'da yer alır (AES-256 için OE ve UE eklenmiştir), bir EncryptMetadata bayrağı bunlara eşlik eder ve üç alan daha, sırasıyla dizelere, akışlara ve gömülü dosyalara uygulanan şifreleme filtrelerini adlandırır
Bu kaydın değeri, sizin için hiçbir şeyi yorumlamamasıdır. Ham sözlüğü geri verir ve sonuçları sizin çıkarmanıza bırakır, ki bu tam olarak bir denetimin ihtiyaç duyduğu şeydir. Şifreli içinde düz metin durumu StringFilterIdentity ve StreamFilterIdentity'de ortaya çıkar: ikisinden biri doğruysa, belgenin şifrelenmiş durumu ne bildirirse bildirsin, karşılık gelen veri Identity filtresinden dokunulmadan geçer. "Bir /Encrypt sözlüğü var" noktasında duran bir tarayıcı, dizeleri ve akışları açık halde otururken böyle bir dosyayı korunmuş olarak adlandıracaktır. Aynı ince ayrım meta veri için de geçerlidir. EncryptMetadata false olduğunda XMP paketi herhangi bir indeksleyici için okunabilir kalırken sayfa içeriği kalmaz, bu da yönlendirme kurallarınızın bir başlık veya yazar alanına dayandığı anda bilinmeye değer bir şeydir
Düz API ile kısa bir güvenlik incelemesi
Çoğu iş akışı için dört düz çağrı, gündelik soruları yanıtlar. LoadFromFile başarı durumunda 1 döndürür ve belge açıldıktan sonra şifreleme denetleyicileri onun çözülmüş durumuna göre rapor verir:
var
PDF: TPDFlib;
begin
PDF := TPDFlib.Create;
try
if PDF.LoadFromFile('contract.pdf', UserPassword) <> 1 then
raise Exception.Create('Open failed: wrong password or damaged file');
Writeln('status : ', PDF.EncryptionStatus); // çözülmüş / şifreli / bilinmiyor
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // RC4'e karşı AES ailesi
Writeln('strength : ', PDF.EncryptionStrength); // anahtar uzunluğu sınıfı
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
CheckPassword, tek satırlık imzasının ima ettiğinden daha fazla önem taşır. PDF, eşit olmayan güce sahip iki parola tanımlar. Dosyayı hiç açabilmek için kullanıcı parolası gereklidir. Sahip parolası tam haklar verir ve her izin bitini geçersiz kılar. Diskteki baytlar her iki durumda da aynıdır, ancak sahip parolası altında açılan bir oturum, kullanıcı parolası oturumunun yapamayacağı şeyleri yapabilir, bu yüzden hangi kimlik bilgisinin sunulduğunu kaydetmeyen bir denetim, gerçeğin yalnızca yarısını kaydediyordur. Sınıf katmanı bu ayrımı sorgulanabilir hale getirir. TPDFDocument.HasUserPassword ve HasOwnerPassword, dosyanın neyi gerektirdiğini bildirirken, IsUserPassword ve IsOwnerPassword, geçerli oturumu gerçekte hangi parolanın açtığını bildirir. Bu gerçeği günlüğe kaydedin. Parola değerlerinin kendilerini asla günlüğe kaydetmeyin
Strength merdiveni: "AES-256" iki şey anlamına geldiğinde
Düz Encrypt ve EncryptFile fonksiyonları, beş anlamlı değere sahip bir tam sayı Strength alır: 40 bit RC4 için 0, 128 bit RC4 için 1, Acrobat 7'den itibaren okunabilir 128 bit AES için 2, Acrobat 9 ile tanıtılan 256 bit AES için 3 ve Acrobat X ve sonrasının gerektirdiği 256 bit AES için 4
İlginç kısım, 3 ve 4'ün her ikisinin de AES-256 olarak etiketlenmiş olması ama aynı şema olmamalarıdır. Strength 3, Acrobat 9'un gönderdiği ve ISO'nun hiç benimsemediği geçici bir tasarım olan güvenlik işleyici revizyon 5'e eşlenir. Strength 4 ise, anahtar türetme fonksiyonu güçlendirilip ISO 32000-2'de standartlaştırılan revizyon 6'ya eşlenir. Bugün oluşturduğunuz bir belge için 4 yerine 3'ü seçmek için hiçbir neden yoktur. Bir denetim için ise bu fark belirleyicidir: "ISO 32000-2'ye göre AES-256" diye okunan bir politika yalnızca R6 tarafından karşılanır ve kendini AES-256 olarak adlandıran bir R5 dosyası, saf bir strength kontrolünü geçerken bu politikayı başaramaz. Sınıf katmanı ikisini isimle ayrı tutar, R5 için esAES256Bit ile R6 için esAES256BitAcroX, ve EncryptionAcroX özelliği revizyon sorusunu tek bir boole ile yanıtlar
İzin bitleri ve anahtar uzunluğuna ilişkin ince baskı hükümleri
EncodePermissions, Encrypt ve EncryptFile'ın beklediği tam sayıya sekiz bayrağı paketler. Yazdır, kopyala, değiştir ve not ekle temel kümeyi oluşturur; alanları doldur, erişilebilirlik için kopyala, birleştir ve tam kaliteli yazdırma ise genişletilmiş kümeyi oluşturur. Kütüphanenin kendi şifreleme demosunun açıkça belirttiği ince baskı hükmü, genişletilmiş dördün yalnızca 128 bit ve üzeri güçte etkili olmasıdır. Tam kaliteli yazdırma bayrağı da aynı kurala tabidir: düşük çözünürlüklü yazdırmayı zorlamak için onu temizleyin, 40 bit bir belge sizi görmezden gelecektir, çünkü bu düşürme de 128 bit veya daha güçlü şifreleme gerektirir. "Yalnızca düşük çözünürlüklü yazdırma" politikasını 40 bit bir dosyaya kodlayın, her görüntüleyici yine de tam kalitede yazdıracaktır
Daha derin soru bu bitleri kimin uyguladığıdır ve cevap, güvenebileceğiniz hiç kimsenin uygulamadığıdır. İzinler, kriptografik kısıtlamalar değil, uyumlu okuyuculara yönelik talimatlardır. Şifre çözme anahtarı, kopyalamaya izin verilsin ya da verilmesin aynıdır, bu yüzden kilitlenmiş bir izin kümesi yalnızca dürüst görüntüleyicileri dürüst tutar. Bitleri görmezden gelmeyi seçen bir okuyucu hiçbir kriptografik engelle karşılaşmaz. Yükümlülük çıkarmayı caydırmak değil engellemekse, dosyanın bir kullanıcı parolasına ve iş akışının bunun etrafında süreç düzeyinde kontrollere ihtiyacı vardır ve bir denetim raporu, bir izin bayrağını kilit gibi ele almak yerine her dosyanın gerçekte bu iki rejimden hangisi altında olduğunu belirtmelidir
Politikayı ayarlamak ve uygulandığını kanıtlamak
Mevcut dosyalara şifreleme uygulamak, onları nesne ağacına yüklemeyi gerektirmez. EncryptFile, girdiden çıktıya tek bir çağrıda işler ve denetim döngüsü, diske ne indiğini doğrulamak için sonucu yeniden açar. Ürünle birlikte gelen şifreleme demosu, aynı yaz-sonra-geri-oku şeklini izler:
var
PDF: TPDFlib;
R: Integer;
begin
PDF := TPDFlib.Create;
try
R := PDF.EncryptFile('in.pdf', 'out.pdf', 'owner-secret', 'user-secret', 4,
PDF.EncodePermissions(1, 0, 0, 0, // yazdırmaya izin verilir; kopyalama/değiştirme/notlar reddedilir
0, 0, 0, 1)); // genişletilmiş küme: yalnızca tam kaliteli yazdırma
if (R = 1) and (PDF.LoadFromFile('out.pdf', 'user-secret') = 1) then
begin
Writeln('algorithm = ', PDF.EncryptionAlgorithm);
Writeln('strength = ', PDF.EncryptionStrength);
Writeln('owner pw accepted: ', PDF.CheckPassword('owner-secret'));
end;
finally
PDF.Free;
end;
end;
Belge katmanında çalışan ekipler, bit paketleme yerine tipli kümelerle aynı işlemi elde eder, ki bu kod incelemesinden çok daha az göz kırpmayla geçer:
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
Her iki durumda da geri okuma adımı isteğe bağlı bir tören değildir. Aksi halde aylar sonra bir müşterinin makinesinde ortaya çıkacak dağıtım hatalarını yakalar: istenen strength'i sessizce düşüren eski bir kütüphane derlemesi, dizin salt okunur olduğu için hiç yazılmamış bir çıktı yolu, argümanları yanlış sırada giden bir izinler tam sayısı. Üçü de yerel bir duman testini geçer ve sahada başarısız olur, çıktıyı yeniden açmak ise her birini, dosyayı oluşturan çalıştırma sırasında gördüğünüz bir istisnaya dönüştürür. GetEncryptionFingerprint, iş kaydıyla birlikte saklayabileceğiniz kompakt bir değer döndürür, böylece daha sonraki bir karşılaştırma, ikisini de yeniden açmadan iki çıktının aynı şifreleme yapılandırmasını paylaşıp paylaşmadığını söyleyebilir
Kodlanmaya değer denetim yanlış pozitifleri
Birkaç kalıp, güvenilir biçimde güvenlik tarayıcılarını yanlış sonuca iter ve her biri çok parçalı bir soruyu evet-hayır cevabına indirgemekten kaynaklanır. Identity şifreleme filtresi en temiz örnektir. Bir /Encrypt sözlüğü mevcuttur, dosya şifreli olarak bildirilir ve yine de dizeler ve akışlar Identity filtresinden değişmeden geçer, bu yüzden gerçek içerik düz metindir. Herhangi bir şeyi korunmuş ilan etmeden önce StringFilterIdentity ve StreamFilterIdentity'yi okumak çözümdür
Meta veri ayrımı daha inceliklidir. EncryptMetadata, belgenin geri kalanıyla her iki yönde de çelişebilir, şifreli bir dosyayı okunabilir bir XMP paketiyle bırakabilir ya da daha az sıklıkla tam tersini yapabilir. "Dosya şifreli" ifadesi, meta verisinin şifreli olup olmadığı hakkında hiçbir şey söylemez, bu da bir indeksleyici ya da yönlendirme kuralı başlığa uzandığı anda önem kazanır. Gömülü dosyalar üçüncü bir eksen ekler: PDF, yalnızca ekler için özel bir şifreleme filtresine izin verir, bu yüzden ekler, aksi halde açık olan bir belgenin tek şifreli parçası ya da şifreli bir belgenin tek düz metin parçası olabilir. Üç filtre atamasını dizeler, akışlar ve gömülü dosyalar için ayrı alanlar olarak yakalayın, bu tuzakların hiçbiri sizi yakalayamaz. Tek bir boole saklayın, yanlış çağrı yalnızca an meselesidir
Şifrelemeyi kaldırmak ve yeni dosyalar için seçmek
Bir denetim genellikle korumayı kaldırma kararıyla sona erer ve buradaki engel mekanikler değildir. DecryptFile(InputFileName, OutputFileName, Password), tam yükleme olmadan şifresi çözülmüş bir kopya yazar ve bir dosya zaten açıldığında yüklenmiş belgenin Decrypt'i aynı işi bellekte yapar. İkisi de geçerli bir parola gerektirir; hiçbiri kriptografiyi atlamaz. Gerçek kapı kod değil politikadır, bu yüzden alım kurallarınız kaldırmaya ne zaman izin verildiğini açıkça belirtsin ve buna yetki veren parola sınıfını kaydetsin, çünkü teknik adımın kendisi hiçbir iz bırakmaz
Yeni çıktı için seçim, beş Strength değerinin ima ettiğinden daha dardır. Dosyaları Acrobat X'ten daha eski görüntüleyicilerde açmanız gerekmedikçe Strength 4, AES-256 revizyon 6 kullanın. Strength 2, AES-128, yükseltilemeyen yaşlı bir görüntüleyici filosu için pragmatik tabandır. 0 ve 1'deki RC4 seçenekleri, tarihsel arşivleri okuyup denetleyebilmeniz içindir, onlarla yeni bir şey üretebilmeniz için değil; 2026 tasarımında onlara yönelmek, yukarı akıştaki bir gereksinimin bayatladığının işaretidir
Şifreleme durumu doğrudan imzalama kararlarını besler, çünkü belgeleri doğrulayan ve imzalayan bir çalışma tezgahı, bu denetimin dayandığı aynı geri okuma disiplinine ihtiyaç duyar. Bu zemin uyumluluk ve imzalama çalışma tezgahı makalesinde ele alınır. Bir toplu işlem, EncryptFile'ı binlerce büyük belge genelinde uyguladığında, büyük PDF'ler için doğrudan erişim rehberi, çalışırken belleği nasıl düz tutacağınızı gösterir. Eksiksiz şifreleme API referansı PDF Library for Delphi ürün sayfasında bulunur