Pular para o conteúdo principal

Validate signatures - PKI Express

PKI Express opens a signed file on your server, lists its signers and, when asked, validates each signature: PDF signatures (PAdES), CMS/CAdES files (.p7s) and XML signatures. PKI Express added the PAdES and CAdES explorers in 1.3.0 and XML in 1.25.0.

The code is PHP, from the PKI Suite samples, the only language with samples for the three formats; it uses lacuna/pki-express (1.17.0).

Flow​

  1. Create the explorer for the format: PadesSignatureExplorer, CadesSignatureExplorer or XmlSignatureExplorer.
  2. Apply the trust settings (see Which certificates are trusted).
  3. Set the signed file and validate = true; without it, the explorer only inspects the signatures.
  4. Call open(), which runs PKI Express's open-pades, open-cades or open-xml command and returns the signers.
  5. Read each signer's certificate, signing time and validationResults.

PDF signatures (PAdES)​

$sigExplorer = new PadesSignatureExplorer();
Util::setPkiDefaults($sigExplorer);
$sigExplorer->setSignatureFile(StorageMock::getDataPath($fileId));
$sigExplorer->validate = true;
$signature = $sigExplorer->open();

CAdES signatures​

$sigExplorer = new CadesSignatureExplorer();
Util::setPkiDefaults($sigExplorer);
$sigExplorer->setSignatureFile(StorageMock::getDataPath($fileId));
$sigExplorer->validate = true;
$signature = $sigExplorer->open();

To also get the signed content, set the path where PKI Express writes it, with setExtractContentPath; the Java, Node.js and Python samples do this, and check hasEncapsulatedContent before offering the file:

CadesSignatureExplorer sigExplorer = new CadesSignatureExplorer();
Util.setPkiDefaults(sigExplorer);
sigExplorer.setSignatureFile(StorageMock.getDataPath(signatureFile));
sigExplorer.setValidate(true);
String outputFile = StorageMock.generateFileId("pdf");
sigExplorer.setExtractContentPath(StorageMock.getDataPath(outputFile));
CadesSignature signature = sigExplorer.open();
  • The samples save the content as a PDF, whatever its type.
  • For a detached signature, give the signed data with setDataFileFromPath (Java: setDataFile). TODO(docs): no sample shows a detached CAdES signature.

XML signatures​

open() returns an XmlSignature whose signers are the signatures in the document. The PHP explorer needs PKI Express 1.25.1 or later; the Node.js and Python libraries have no XML explorer, and the Java library has one in 1.23.1 but not in 1.20.0.

$sigExplorer = new XmlSignatureExplorer();
Util::setPkiDefaults($sigExplorer);
$sigExplorer->setSignatureFile(StorageMock::getDataPath($fileId));
$sigExplorer->validate = true;
$signatures = $sigExplorer->open()->signers;

Each XML signer also has a type and the signedElement (localName, namespaceUri).

Which certificates are trusted​

By default, PKI Express trusts only certificates issued under ICP-Brasil. The samples' helper adds the roots listed in their configuration and, for development, Lacuna's test root, which accepts the test certificates:

$trustedRoots = $config['pkiExpress']['trustedRoots'];
foreach ($trustedRoots as $root) {
$operator->addTrustedRoot(StorageMock::getResourcePath($root));
}
$operator->trustLacunaTestRoot = $config['trustLacunaTestRoot'];
  • See "Trusting in custom certificates" for Node.js, Java, PHP, Python and Ruby.
  • PKI Express has no security context, unlike Rest PKI: none of its client libraries has one.
  • The Java library can also trust only ICP-Brasil (setTrustOnlyICPBrasil) or only the roots trusted by the operating system (setTrustOnlySystem).

Validation policies​

For PAdES, PKI Express 1.20.0 and later accept a validation policy: pades, pades-with-cert-protection, pki-brazil, pki-brazil-with-cert-protection or adobe-reader. Set it with validationPolicy (PHP) or setPolicy (Java), using StandardSignaturePoliciesForValidation.

  • The Node.js and Python libraries have no validation policy for their explorers. The Node.js signaturePolicy property applies only when signing.
  • The Java 1.23.1 XML explorer takes an XmlPoliciesForValidation.
  • Since PKI Express 1.23.0, trustUncertifiedSigningTime (PHP) or setTrustUncertifiedSigningTime (Java) accepts the signing time the signer declared as the date reference.

Read the results​

  • A PAdES or CAdES signature has signers; each has its certificate, signingTime, messageDigest, signaturePolicy, timestamps and validationResults. A PAdES signer also has isDocumentTimestamp and signatureFieldName.
  • validationResults has isValid(), hasErrors(), hasWarnings() and getSummary(), and converts to a text that lists every check.
  • The certificate has subjectName, emailAddress, issuerName, serialNumber, the validity dates and, for ICP-Brasil certificates, pkiBrazil (certificateType, cpf, cnpj, responsavel, companyName, dateOfBirth, RG and OAB).

The sample's page shows each signer with a "valid" or "invalid" badge from isValid(), the signing time, the message digest, the policy, the ICP-Brasil fields and the full text of the validation results.

  • PKI Express's return code 14 (ValidationFailed) and the validation errors are listed in Return codes.
  • TODO(docs): whether open-* with --validate fails with code 14 for an invalid signature or returns the results with errors (the samples read isValid() per signer).

See also​

View as Markdown