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
- Create the explorer for the format:
PadesSignatureExplorer,CadesSignatureExplorerorXmlSignatureExplorer. - Apply the trust settings (see Which certificates are trusted).
- Set the signed file and
validate = true; without it, the explorer only inspects the signatures. - Call
open(), which runs PKI Express'sopen-pades,open-cadesoropen-xmlcommand and returns the signers. - 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
signaturePolicyproperty applies only when signing. - The Java 1.23.1 XML explorer takes an
XmlPoliciesForValidation. - Since PKI Express 1.23.0,
trustUncertifiedSigningTime(PHP) orsetTrustUncertifiedSigningTime(Java) accepts the signing time the signer declared as the date reference.
Read the results
- A PAdES or CAdES signature has
signers; each has itscertificate,signingTime,messageDigest,signaturePolicy,timestampsandvalidationResults. A PAdES signer also hasisDocumentTimestampandsignatureFieldName. validationResultshasisValid(),hasErrors(),hasWarnings()andgetSummary(), 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--validatefails with code 14 for an invalid signature or returns the results with errors (the samples readisValid()per signer).