Pular para o conteúdo principal

Printer-friendly version - PKI Express

A printed copy of a signed PDF loses its digital signatures. A printer-friendly version tells the reader who signed the document and how to get the signed file back: PKI Express validates the signatures, marks every page with the signers' names and a verification code, and adds a manifest page with a QR code. Your site then looks the document up by that code. PKI Express added PDF editing (the edit-pdf command) in 1.3.0, "enabling generation of printer-friendly versions".

The code is Node.js, from the PKI Suite samples, with pki-express (1.16.2); the Python sample does the same.

Flow​

  1. Generate a verification code for the signed PDF and store it with the file.
  2. Open and validate the PDF's signatures with PadesSignatureExplorer.
  3. Build the marks with PdfHelper: the signers on every page, and a manifest on a new page.
  4. Call PdfMarker.apply(), which runs PKI Express's edit-pdf command and writes the marked PDF.
  5. When someone types the code on your site, look the file up and show or download it.

1. The verification code​

The sample generates a 16-character code from cryptographically strong random bytes and stores the code and the file id in the web session, both ways. Store them in your database instead.

let verificationCode = StorageMock.getVerificationCode(req.session, fileId);
if (!verificationCode) {
verificationCode = Util.generateVerificationCode();
StorageMock.setVerificationCode(req.session, fileId, verificationCode);
}

The code protects access to your documents: the Java library has an AlphaCode class to generate it, described in Generating alphanumeric codes.

2. Open the signatures​

const sigExplorer = new PadesSignatureExplorer();
Util.setPkiDefaults(sigExplorer);
sigExplorer.validate = true;
sigExplorer.setSignatureFileFromPathSync(pdfPath);
sigExplorer.open().then((signature) => { /* build the marks from signature.signers */ });

Each signer has its certificate, signingTime and validationResults; see Validate signatures.

3. Mark every page​

PdfHelper is a fluent API that builds marks, containers and elements (text, image, QR code); PdfMarker holds the list of marks. The sample puts the ICP-Brasil logo in the bottom-right corner and the message along the bottom and the right edge of every page:

const pdfMarker = new PdfMarker();
Util.setPkiDefaults(pdfMarker);
pdfMarker.setFileFromPathSync(pdfPath);
const pdf = new PdfHelper();
pdfMarker.marks.push(
pdf.mark()
.onAllPages()
.onContainer(pdf.container().width(1).anchorRight(1).height(1)
.anchorBottom(1))
.addElement(
pdf.imageElement()
.withOpacity(75)
.withImageContent(Util.getIcpBrasilLogoContent(), 'image/png'),
),
);
pdfMarker.marks.push(
pdf.mark()
.onAllPages()
.onContainer(pdf.container().height(2).anchorBottom().varWidth()
.margins(1.5, 3.5))
.addElement(pdf.textElement().withOpacity(75).addSectionFromText(allPagesMessage)),
);
  • allPagesMessage names the signers and gives the verification site and the code.
  • Sizes and positions are in centimeters by default (measurementUnits).
  • A text element can be rotated with rotate90CounterClockwise(), as the sample does for the right edge.

4. Add the manifest page​

A mark with onNewPage() adds a page. The sample fills it from the top down: the logo, a QR code with the verification link, the title, the code, one line per signer with a valid or invalid icon, and the verification link.

const manifestMark = pdf.mark()
.onNewPage()
.onContainer(pdf.container().varWidthAndHeight().margins(2.54, 2.54));
manifestMark.addElement(
pdf.qrCodeElement()
.onContainer(pdf.container().height(elementHeight).anchorTop(verticalOffset)
.width(elementHeight)
.anchorRight())
.withQRCodeData(verificationLink),
);
// ... more elements
pdfMarker.marks.push(manifestMark);
outputFile = `${uuidv4()}.pdf`;
pdfMarker.outputFile = path.join(APP_ROOT, 'app-data', outputFile);
return pdfMarker.apply();
  • apply() writes the marked PDF to outputFile, or over the original with overwriteOriginalFile.
  • TODO(docs): whether the marked copy keeps the original signatures (PKI SDK's PdfMarker removes them; see the PKI SDK page).

5. Check a code​

The verification page parses the code, finds the file and opens its signatures again to show them:

const verificationCode = Util.parseVerificationCode(req.query.code);
const fileId = StorageMock.lookupVerificationCode(req.session, verificationCode);
const sigExplorer = new PadesSignatureExplorer();
Util.setPkiDefaults(sigExplorer);
sigExplorer.setSignatureFileFromPathSync(StorageMock.getDataPath(fileId));
sigExplorer.validate = true;
sigExplorer.open().then((signature) => { /* render the signers and a link to the file */ });

For a CAdES file​

For a .p7s, the Node.js sample opens it with CadesSignatureExplorer and marks an empty PDF that ships with the sample, so the result is a manifest that lists the signers, with the verification code and a QR code.

In each language​

LibraryPdfMarkerPdfHelper (fluent API)
Node.jsyes; setFileFromPath, outputFile, marks, apply()yes
Javayesyes
PHPyes; setFile, setOutputFile, apply()no: build PdfMark objects
Pythonyes; set_file_from_path, output_file, marks, apply()yes
Rubynono

See also​

View as Markdown