Pular para o conteúdo principal

Validar assinaturas - PKI Express

O PKI Express abre um arquivo assinado no seu servidor, lista os signatários e, quando solicitado, valida cada assinatura: assinaturas em PDF (PAdES), arquivos CMS/CAdES (.p7s) e assinaturas XML. O PKI Express acrescentou os exploradores de PAdES e CAdES na 1.3.0 e o de XML na 1.25.0.

O código é PHP, dos samples do PKI Suite, a única linguagem com samples para os três formatos; ele usa o lacuna/pki-express (1.17.0).

Fluxo​

  1. Crie o explorador do formato: PadesSignatureExplorer, CadesSignatureExplorer ou XmlSignatureExplorer.
  2. Aplique as configurações de confiança (veja Quais certificados são confiáveis).
  3. Defina o arquivo assinado e validate = true; sem isso, o explorador só inspeciona as assinaturas.
  4. Chame open(), que executa o comando open-pades, open-cades ou open-xml do PKI Express e devolve os signatários.
  5. Leia o certificado, a data da assinatura e o validationResults de cada signatário.

Assinaturas em PDF (PAdES)​

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

Assinaturas CAdES​

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

Para obter também o conteúdo assinado, defina o caminho em que o PKI Express o grava, com setExtractContentPath; os samples em Java, Node.js e Python fazem isso e verificam hasEncapsulatedContent antes de oferecer o arquivo:

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();
  • Os samples gravam o conteúdo como PDF, qualquer que seja o tipo dele.
  • Para uma assinatura destacada (detached), informe os dados assinados com setDataFileFromPath (Java: setDataFile). TODO(docs): nenhum sample mostra uma assinatura CAdES destacada.

Assinaturas XML​

open() devolve um XmlSignature cujos signers são as assinaturas do documento. O explorador em PHP exige o PKI Express 1.25.1 ou posterior; as bibliotecas Node.js e Python não têm explorador de XML, e a biblioteca Java tem um na 1.23.1, mas não na 1.20.0.

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

Cada signatário XML também tem um type e o signedElement (localName, namespaceUri).

Quais certificados são confiáveis​

Por padrão, o PKI Express só confia em certificados emitidos na ICP-Brasil. A função auxiliar dos samples acrescenta as raízes listadas na configuração deles e, para desenvolvimento, a raiz de teste da Lacuna, que aceita os certificados de teste:

$trustedRoots = $config['pkiExpress']['trustedRoots'];
foreach ($trustedRoots as $root) {
$operator->addTrustedRoot(StorageMock::getResourcePath($root));
}
$operator->trustLacunaTestRoot = $config['trustLacunaTestRoot'];
  • Veja "Confiando em certificados que não sejam da ICP-Brasil" para Node.js, Java, PHP, Python e Ruby.
  • O PKI Express não tem contexto de segurança, ao contrário do Rest PKI: nenhuma das bibliotecas cliente dele tem um.
  • A biblioteca Java também pode confiar só na ICP-Brasil (setTrustOnlyICPBrasil) ou só nas raízes confiáveis do sistema operacional (setTrustOnlySystem).

Políticas de validação​

No PAdES, o PKI Express 1.20.0 e posteriores aceitam uma política de validação: pades, pades-with-cert-protection, pki-brazil, pki-brazil-with-cert-protection ou adobe-reader. Defina-a com validationPolicy (PHP) ou setPolicy (Java), usando StandardSignaturePoliciesForValidation.

  • As bibliotecas Node.js e Python não têm política de validação nos exploradores. A propriedade signaturePolicy do Node.js só vale na assinatura.
  • O explorador de XML do Java 1.23.1 recebe um XmlPoliciesForValidation.
  • Desde o PKI Express 1.23.0, trustUncertifiedSigningTime (PHP) ou setTrustUncertifiedSigningTime (Java) aceita como referência de data a data da assinatura declarada pelo signatário.

Ler os resultados​

  • Uma assinatura PAdES ou CAdES tem signers; cada um tem o seu certificate, signingTime, messageDigest, signaturePolicy, timestamps e validationResults. Um signatário PAdES também tem isDocumentTimestamp e signatureFieldName.
  • validationResults tem isValid(), hasErrors(), hasWarnings() e getSummary(), e vira um texto que lista todas as verificações.
  • O certificado tem subjectName, emailAddress, issuerName, serialNumber, as datas de validade e, em certificados ICP-Brasil, pkiBrazil (certificateType, cpf, cnpj, responsavel, companyName, dateOfBirth, RG e OAB).

A página do sample mostra cada signatário com um selo "valid" ou "invalid" a partir de isValid(), a data da assinatura, o resumo da mensagem (message digest), a política, os campos ICP-Brasil e o texto completo dos resultados da validação.

  • O código de retorno 14 (ValidationFailed) do PKI Express e os erros de validação estão nos códigos de retorno.
  • TODO(docs): se o open-* com --validate falha com o código 14 para uma assinatura inválida ou devolve os resultados com erros (os samples leem isValid() por signatário).

Veja também​

Ver em Markdown