Blog
All Blog Posts | Next Post | Previous Post
A quick look at PDF encryption and decryption with TMS Cryptography Pack
Today
TMS Cryptography Pack already dealt with PDF files with PAdES, an ETSI standard to sign PDF with RSA or ECDSA private keys, that inserts signature blocks within documents. These signatures use the Cryptographic Message Syntax (CMS) format, as described in RFC 5652. If valid and generated with trusted certificates/keys, they are recognized by all mainstream PDF readers, such as Acrobat, FoxIT or PDF X-Change.
However, users may also want to programmatically encrypt and decrypt PDF files, sometimes in bulk operations, without opening any PDF tool. This feature is now available in TMS Cryptography Pack and this short post just shows how easy it is to use.
Introducing TPdfEncryptor
The new TPdfEncryptor class is straightforward.
TPdfEncryptor = class(TTMSCryptBase)
private
FCrypto: IPdfCryptoProvider;
public
constructor Create(AOwner: TComponent; const ACrypto: IPdfCryptoProvider);
function Encrypt(const APdf: TBytes; const AUserPassword: string;
const AOwnerPassword: string = '';
APermissions: TPdfPermissions = [Low(TPdfPermission)..High(TPdfPermission)]): TBytes;
procedure EncryptFile(const ASource, ADest, AUserPassword: string;
const AOwnerPassword: string = '';
APermissions: TPdfPermissions = [Low(TPdfPermission)..High(TPdfPermission)]);
function Decrypt(const APdf: TBytes; const APassword: string): TBytes;
procedure DecryptFile(const ASource, ADest, APassword: string);
end;
The crypto has been completely isolated and can be accessed through a specific interface that wraps the usual primitives such as random sequence generation, SHA2 (all key sizes) and the AES (all key sizes too).
IPdfCryptoProvider = interface
['{6F1C7A52-3B1E-4D0C-9A57-2E8D4C0B7A11}']
function RandomBytes(ACount: Integer): TBytes;
function Hash(AAlgo: TPdfHashAlgo; const AData: TBytes): TBytes;
function AesCbcEncryptNoPad(const AKey, AIV, AData: TBytes): TBytes;
function AesCbcDecryptNoPad(const AKey, AIV, AData: TBytes): TBytes;
end;
Using TPdfEncryptor
Whereas encrypting and decrypting a PDF file require some amount of code, as for signing and verifying, the high-level TPdfEncryptor class makes these operations extremely simple.
Here is a PDF encryption example from the VCL demos (it also works with FMX and in console mode). This app uses a form, 2 buttons, a TMemo and a TOpenDialog.
procedure TMainForm.EncryptBtnClick(Sender: TObject);
var
s: string;
begin
if OpenDialog.Execute = false then
Exit;
// This is a demo. In a real app, choose a stronger password!
PdfEncryptor := TPdfEncryptor.Create(nil, TTmsPdfCrypto.Create); // uses TTmsPdfCrypto for the crypto engine
try
s := '.\' + TPath.GetFileNameWithoutExtension(OpenDialog.FileName) + '.enc.pdf'; // or keep the initial name
PdfEncryptor.EncryptFile(OpenDialog.FileName, s, 'AnyPassword');
MainMemo.Lines.Add('File encrypted: ' + s);
finally
PdfEncryptor.Free;
end;
end;And decrypting isn't more complicated.
procedure TMainForm.DecryptBtnClick(Sender: TObject);
var
s: string;
begin
if OpenDialog.Execute = false then
Exit;
// This is a demo. In a real app, choose a stronger password.
PdfEncryptor := TPdfEncryptor.Create(nil, TTmsPdfCrypto.Create);
try
s := '.\' + TPath.GetFileNameWithoutExtension(OpenDialog.FileName) + '.dec.pdf'; // or keep the initial name
PdfEncryptor.DecryptFile(OpenDialog.FileName, s, 'AnyPassword');
MainMemo.Lines.Add('File decrypted: ' + s);
finally
PdfEncryptor.Free;
end;
end;
Conclusion
PDF encryption/decryption has been on the back burner for quite some time and is now in TMS Cryptography Pack with a new class: TPdfEncryptor. It can be used in any Delphi application for a single use or batch operations, for which manual encryption/decryption can be quite painful.
Bernard Roussely
This blog post has not received any comments yet.
All Blog Posts | Next Post | Previous Post