C Requires Chilkat v11.7.0+
C
Encrypt and Sign a PDF, and Sign an Encrypted PDF
See more PDF Protection Examples
Demonstrates signing together with encryption. A pending encrypt is applied by SignPdf before it signs, so one call produces a PDF that is both encrypted and signed. A PDF that is already encrypted can be signed too, and stays encrypted. When it was opened with only the user password its permissions decide: adding a signature field needs both the modify and the annotate permission. Loading the PDF with its owner password lifts that.Chilkat C Downloads
#include <C_CkCert.h>
#include <C_CkPdf.h>
#include <C_CkJsonObject.h>
void ChilkatSample(void)
{
BOOL success;
HCkCert cert;
HCkPdf pdf;
HCkJsonObject json;
HCkJsonObject jsonOut;
HCkJsonObject sigOpts;
HCkPdf check;
HCkJsonObject empty;
HCkJsonObject info;
HCkJsonObject sigInfo;
BOOL verified;
HCkPdf owner;
HCkPdf twice;
success = FALSE;
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// The PDF used in this example is available at two_page_memo.pdf
// The signing certificate, with its private key.
cert = CkCert_Create();
success = CkCert_LoadPfxFile(cert,"qa_data/pfx/myPdfSigningCert.pfx","secret");
if (success == FALSE) {
printf("%s\n",CkCert_lastErrorText(cert));
CkCert_Dispose(cert);
return;
}
pdf = CkPdf_Create();
success = CkPdf_LoadFile(pdf,"qa_data/pdf/two_page_memo.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(pdf));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
return;
}
// Encrypt with AES-256 and do not permit modifying.
CkPdf_putUserPassword(pdf,"user-secret");
CkPdf_putOwnerPassword(pdf,"owner-secret");
json = CkJsonObject_Create();
CkJsonObject_UpdateBool(json,"permissions.modify",FALSE);
jsonOut = CkJsonObject_Create();
success = CkPdf_Protection(pdf,"encrypt",json,jsonOut);
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(pdf));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
return;
}
// The encryption is still pending. SignPdf applies it first and signs the encrypted result.
success = CkPdf_SetSigningCert(pdf,cert);
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(pdf));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
return;
}
sigOpts = CkJsonObject_Create();
CkJsonObject_UpdateBool(sigOpts,"invisibleSignature",TRUE);
CkJsonObject_UpdateInt(sigOpts,"signingCertificateV2",1);
CkJsonObject_UpdateInt(sigOpts,"signingTime",1);
success = CkPdf_SignPdf(pdf,sigOpts,"qa_output/memo_encrypted_signed.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(pdf));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
return;
}
// The result is encrypted and signed.
check = CkPdf_Create();
CkPdf_putUserPassword(check,"user-secret");
success = CkPdf_LoadFile(check,"qa_output/memo_encrypted_signed.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(check));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
return;
}
empty = CkJsonObject_Create();
info = CkJsonObject_Create();
success = CkPdf_Protection(check,"getInfo",empty,info);
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(check));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
return;
}
printf("algorithm: %s\n",CkJsonObject_stringOf(info,"loaded.algorithm"));
printf("signatures: %d\n",CkPdf_getNumSignatures(check));
sigInfo = CkJsonObject_Create();
verified = CkPdf_VerifySignature(check,0,sigInfo);
printf("signature verifies: %d\n",verified);
// Signing an encrypted PDF. This one was opened with only the user password, and its
// permissions do not allow modifying, so another signature is refused.
success = CkPdf_SetSigningCert(check,cert);
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(check));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
return;
}
success = CkPdf_SignPdf(check,sigOpts,"qa_output/memo_signed_twice.pdf");
if (success == FALSE) {
printf("A second signature was refused: the permissions do not allow it.\n");
}
// Loaded with the owner password, the same PDF can be signed. It stays encrypted, and the
// first signature stays valid because the new one is added as an incremental update.
owner = CkPdf_Create();
CkPdf_putUserPassword(owner,"user-secret");
CkPdf_putOwnerPassword(owner,"owner-secret");
success = CkPdf_LoadFile(owner,"qa_output/memo_encrypted_signed.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(owner));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
CkPdf_Dispose(owner);
return;
}
success = CkPdf_SetSigningCert(owner,cert);
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(owner));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
CkPdf_Dispose(owner);
return;
}
success = CkPdf_SignPdf(owner,sigOpts,"qa_output/memo_signed_twice.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(owner));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
CkPdf_Dispose(owner);
return;
}
twice = CkPdf_Create();
CkPdf_putUserPassword(twice,"user-secret");
success = CkPdf_LoadFile(twice,"qa_output/memo_signed_twice.pdf");
if (success == FALSE) {
printf("%s\n",CkPdf_lastErrorText(twice));
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
CkPdf_Dispose(owner);
CkPdf_Dispose(twice);
return;
}
printf("signatures after signing with owner rights: %d\n",CkPdf_getNumSignatures(twice));
verified = CkPdf_VerifySignature(twice,0,sigInfo);
printf("first signature still verifies: %d\n",verified);
verified = CkPdf_VerifySignature(twice,1,sigInfo);
printf("second signature verifies: %d\n",verified);
// Sample output:
// algorithm: aes-256
// signatures: 1
// signature verifies: True
// A second signature was refused: the permissions do not allow it.
// signatures after signing with owner rights: 2
// first signature still verifies: True
// second signature verifies: True
CkCert_Dispose(cert);
CkPdf_Dispose(pdf);
CkJsonObject_Dispose(json);
CkJsonObject_Dispose(jsonOut);
CkJsonObject_Dispose(sigOpts);
CkPdf_Dispose(check);
CkJsonObject_Dispose(empty);
CkJsonObject_Dispose(info);
CkJsonObject_Dispose(sigInfo);
CkPdf_Dispose(owner);
CkPdf_Dispose(twice);
}