Pular para o conteúdo principal

Versão para impressão - PKI Express

Uma cópia impressa de um PDF assinado perde as assinaturas digitais. A versão para impressão diz ao leitor quem assinou o documento e como obter de volta o arquivo assinado: o PKI Express valida as assinaturas, marca em todas as páginas os nomes dos signatários e um código de verificação e acrescenta uma página de manifesto com um QR code. O seu site, depois, localiza o documento por esse código. O PKI Express acrescentou a edição de PDFs (o comando edit-pdf) na 1.3.0, justamente para gerar versões para impressão.

O código é Node.js, dos samples do PKI Suite, com o pki-express (1.16.2); o sample em Python faz o mesmo.

Fluxo​

  1. Gere um código de verificação para o PDF assinado e guarde-o junto com o arquivo.
  2. Abra e valide as assinaturas do PDF com o PadesSignatureExplorer.
  3. Monte as marcas com o PdfHelper: os signatários em todas as páginas e um manifesto em uma página nova.
  4. Chame PdfMarker.apply(), que executa o comando edit-pdf do PKI Express e grava o PDF marcado.
  5. Quando alguém digitar o código no seu site, localize o arquivo e mostre-o ou ofereça o download.

1. O código de verificação​

O sample gera um código de 16 caracteres a partir de bytes aleatórios criptograficamente fortes e guarda, na sessão web, o código e o id do arquivo nos dois sentidos. Guarde-os no seu banco de dados.

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

O código protege o acesso aos seus documentos: a biblioteca Java tem a classe AlphaCode para gerá-lo, descrita em Gerando códigos alfanuméricos em Java.

2. Abrir as assinaturas​

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

Cada signatário tem certificate, signingTime e validationResults; veja Validar assinaturas.

3. Marcar todas as páginas​

O PdfHelper é uma API fluente que monta marcas, containers e elementos (texto, imagem, QR code); o PdfMarker guarda a lista de marcas. O sample põe o logotipo da ICP-Brasil no canto inferior direito e a mensagem ao longo da borda inferior e da borda direita de todas as páginas:

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 cita os signatários e informa o site de verificação e o código.
  • Tamanhos e posições ficam em centímetros por padrão (measurementUnits).
  • Um elemento de texto pode ser girado com rotate90CounterClockwise(), como o sample faz na borda direita.

4. Acrescentar a página de manifesto​

Uma marca com onNewPage() acrescenta uma página. O sample a preenche de cima para baixo: o logotipo, um QR code com o link de verificação, o título, o código, uma linha por signatário com um ícone de válido ou inválido e o link de verificação.

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() grava o PDF marcado em outputFile, ou sobre o original com overwriteOriginalFile.
  • TODO(docs): se a cópia marcada mantém as assinaturas originais (o PdfMarker do PKI SDK as remove; veja a página do PKI SDK).

5. Verificar um código​

A página de verificação interpreta o código, encontra o arquivo e abre de novo as assinaturas para mostrá-las:

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 */ });

Para um arquivo CAdES​

Para um .p7s, o sample em Node.js o abre com o CadesSignatureExplorer e marca um PDF vazio que vem com o sample; o resultado é um manifesto que lista os signatários, com o código de verificação e um QR code.

Em cada linguagem​

BibliotecaPdfMarkerPdfHelper (API fluente)
Node.jssim; setFileFromPath, outputFile, marks, apply()sim
Javasimsim
PHPsim; setFile, setOutputFile, apply()não: monte objetos PdfMark
Pythonsim; set_file_from_path, output_file, marks, apply()sim
Rubynãonão

Veja também​

Ver em Markdown