Contextos de segurança e políticas de assinatura - Rest PKI Core
Ao assinar ou validar, o Rest PKI Core responde a duas perguntas independentes:
| Contexto de segurança | Política de assinatura | |
|---|---|---|
| Pergunta | Em quem confiar? | Como a assinatura deve ser feita ou estar feita? |
| Decide | Em quais raízes a cadeia do certificado do signatário precisa terminar | O formato (PAdES, CAdES, XML), os atributos obrigatórios e proibidos, os algoritmos aceitos, o carimbo de tempo e os dados de LTV |
| Exemplos | PkiBrazil, GovBR, PkiBrazilWithGovBrAndENotariado, um contexto criado no dashboard | PAdES básica, ICP-Brasil AD-RB, Adobe Reader |
| Parâmetro | securityContextId | signaturePolicyId, defaultSignaturePolicyId e acceptableExplicitPolicies, apenas nas rotas do Rest PKI |
Uma assinatura só é válida quando as duas verificações passam: o certificado tem de ser confiável no contexto de segurança, e a assinatura tem de seguir a política. Uma não substitui a outra. Trocar a política não faz o Rest PKI Core confiar em mais certificados, e trocar o contexto de segurança não faz ele aceitar um formato que a política recusa.
Se uma assinatura é qualificada também não depende da política: depende do certificado. Uma assinatura feita com um certificado ICP-Brasil é qualificada mesmo que não siga o padrão PAdES da ICP-Brasil. A política só decide se aquele formato é aceito.
Veja Contextos de segurança para os contextos padrão e para criar os seus.
Um exemplo: assinatura feita no Adobe Acrobat
Um PDF assinado no Adobe Acrobat com um certificado ICP-Brasil, validado com a política PAdES básica e o contexto PkiBrazil, pode
voltar com este erro:
"errors": [
{
"type": "RequiredSignedAttributeMissing",
"message": "Atributo assinado obrigatório faltando",
"detail": "signing-certificate",
"innerValidationResults": null
}
]
O certificado está certo: a cadeia termina na raiz da ICP-Brasil, em que o contexto PkiBrazil confia. O que falha é o formato. O PAdES
exige o atributo assinado signing-certificate, e o formato padrão de assinatura do Acrobat (adbe.pkcs7.detached) não o inclui. Para
aceitar esse PDF, mantenha o contexto de segurança e troque a política pela Adobe Reader.
Como os dois se combinam em cada API
Rotas do Rest PKI
Nas rotas do Rest PKI que o Rest PKI Core atende, você escolhe a política. Isso vale para o início de uma
assinatura PAdES (Api/PadesSignatures) e para a validação (Api/PadesSignatures/Open, usada pelo PadesSignatureExplorer das bibliotecas
cliente):
- Com
securityContextId: o contexto de segurança decide em quem confiar, e a política decide o resto. O contexto substitui as raízes que a política traz, inclusive nas políticas da ICP-Brasil. - Sem
securityContextId: vale a confiança da política. As políticas da ICP-Brasil confiam na ICP-Brasil. As demais não confiam em nenhuma raiz, e a chamada falha comSecurityContextRequired.
APIs do Rest PKI Core
As sessões de assinatura, as assinaturas em duas etapas e a inspeção de assinaturas não recebem política:
- Ao assinar, a política é escolhida pela configuração da instância.
General:DefaultSignaturePolicy(Basic, o padrão, ouWithTime) diz se a assinatura leva carimbo de tempo. ComGeneral:UseBrazilianPdfSigningPoliciesligada, as assinaturas de PDF seguem a ICP-Brasil (AD-RB ou AD-RT). Desligada, o padrão, elas seguem a PAdES básica (ou a PAdES-T). - Ao validar, a inspeção usa a política básica do formato, a PAdES básica no caso de PDF. Ela recusa assinaturas no formato do Adobe
com o erro do exemplo acima. Para aceitá-las, valide pela rota
Api/PadesSignatures/Opencom a política Adobe Reader. - A confiança vem sempre do contexto de segurança: o informado na chamada ou, sem ele, o padrão da organização ou da instância.
Políticas para PDF
Estas são as políticas PAdES. Em .NET, elas estão em StandardPadesSignaturePolicies (namespace Lacuna.RestPki.Api). Em Python, as
constantes de StandardSignaturePolicies (pacote restpki_client) não incluem a Adobe Reader nem a sem LTV: passe o ID.
| Política | ID | O que define | Sem contexto de segurança, confia em |
|---|---|---|---|
Basic | 78d20b33-014d-440e-ad07-929f05d00cdf | PAdES básica, com dados de LTV | Nenhuma raiz: exige contexto |
BasicWithoutLtv | ed93a777-ad5a-49a0-8b67-5aa5dfad1c98 | PAdES básica, sem dados de LTV | Nenhuma raiz: exige contexto |
AdobeReader | aaed831b-fa9d-4732-82fc-8d25f2c16c57 | PAdES básica sem as exigências de atributos e de algoritmos; aceita o formato do Adobe (veja abaixo) | Nenhuma raiz: exige contexto |
PkiBrazil.AdrBasica | 531d5012-4c0d-4b6f-89e8-ebdcc605d7c2 | ICP-Brasil AD-RB (política explícita) | ICP-Brasil |
PkiBrazil.AdrTempo | 10f0d9a5-a0a9-42e9-9523-e181ce05a25b | ICP-Brasil AD-RT, com carimbo de tempo (política explícita) | ICP-Brasil |
PkiBrazil.BasicWithPkiBrazilCerts | 3fec800c-366c-49bf-82c5-2e72154e70f6 | PAdES básica | ICP-Brasil |
PkiBrazil.PadesTWithPkiBrazilCerts | 6a39aeea-a2d0-4754-bf8c-19da15296ddb | PAdES-T, com carimbo de tempo | ICP-Brasil |
As políticas com carimbo de tempo usam o plano de carimbo de tempo do contexto de segurança (veja Configurações de um contexto de segurança).
StandardPadesSignaturePolicies.PkiBrazil também tem AdrCompleta e AdrArquivamento, mas o servidor não as aceita: a chamada falha com
SignaturePolicyNotFound.
Política padrão e políticas explícitas
Na validação, o PDF pode declarar uma política explícita (AD-RB ou AD-RT da ICP-Brasil) ou nenhuma. Dois parâmetros decidem como cada assinatura é validada:
acceptableExplicitPolicieslista as políticas explícitas aceitas. SóPkiBrazil.AdrBasicaePkiBrazil.AdrTempopodem entrar na lista. As outras são implícitas, e a chamada falha comInvalidRequest.defaultSignaturePolicyIdvalida as assinaturas que não declaram política e as que declaram uma política fora da lista. Sem ela, essas assinaturas falham na validação.
Com a Adobe Reader como defaultSignaturePolicyId, as assinaturas PAdES da ICP-Brasil também passam, porque a Adobe Reader exige menos
do que a AD-RB. Para exigir o padrão da ICP-Brasil, use acceptableExplicitPolicies sem defaultSignaturePolicyId (veja o
exemplo).
A política Adobe Reader
A política Adobe Reader (aaed831b-fa9d-4732-82fc-8d25f2c16c57) parte da PAdES básica e relaxa a verificação do formato:
- Não exige os atributos assinados obrigatórios, como o
signing-certificate. - Aceita atributos desconhecidos e atributos que o PAdES proíbe, como o
signing-timedentro da assinatura CMS. - Aceita qualquer algoritmo de hash e de assinatura.
O resto da validação não muda: a integridade do documento, a cadeia do certificado, a revogação e a confiança no contexto de segurança. Por isso a política exige um contexto de segurança, e um certificado fora dele continua sendo recusado.
Ela é uma política implícita: use-a como defaultSignaturePolicyId, nunca em acceptableExplicitPolicies.
Ao assinar, a Adobe Reader gera a assinatura no formato do Adobe (subfilter adbe.pkcs7.detached) e sem dados de LTV. Isso vale no Rest PKI
Core a partir da 4.1.2, pela rota de início de assinatura PAdES do Rest PKI. No Rest PKI, a Adobe Reader serve apenas para validar.
O nome da política não tem relação com o que o Adobe Reader exibe ao abrir o PDF. O Adobe Reader valida com a lista de raízes da própria Adobe (AATL) e com as configurações dele, não com o contexto de segurança do Rest PKI Core. Uma assinatura válida no Rest PKI Core pode aparecer como não verificada no Adobe Reader. Veja Certificados confiados pela Adobe e Validação do Adobe Reader.
Exemplos
Os exemplos validam pela rota Api/PadesSignatures/Open. Nas bibliotecas cliente do Rest PKI, que funcionam com uma chave do Rest PKI
Core, ela é chamada pelo PadesSignatureExplorer (veja Migração do Rest PKI).
Aceitar assinaturas do Adobe de várias hierarquias
Um PDF tem assinaturas da ICP-Brasil (algumas feitas no Adobe Acrobat), do gov.br e do e-Notariado, e você quer validar todas elas. Use o
contexto PkiBrazilWithGovBrAndENotariado, que confia nas três hierarquias, e a política Adobe Reader como padrão.
Python
Com o pacote restpki-client:
from restpki_client import PadesSignatureExplorer, RestPkiClient
ADOBE_READER = 'aaed831b-fa9d-4732-82fc-8d25f2c16c57'
PKI_BRAZIL_WITH_GOVBR_AND_ENOTARIADO = '4bf4409f-db45-4aab-91bf-2c73930ca556'
client = RestPkiClient('https://sua-instancia.exemplo.com.br/', 'SUA_CHAVE_DE_API')
explorer = PadesSignatureExplorer(client)
explorer.signature_file_path = 'documento-assinado.pdf'
explorer.validate = True
explorer.default_signature_policy_id = ADOBE_READER
explorer.security_context_id = PKI_BRAZIL_WITH_GOVBR_AND_ENOTARIADO
signature = explorer.open()
for signer in signature.signers:
name = signer.certificate.subject_name.common_name
results = signer.validation_results
if results is None:
print(name, '- não validada')
elif results.is_valid:
print(name, '- válida')
else:
print(name, '- inválida')
for error in results.errors:
print(' ', error.item_type, error.message, error.detail)
.NET
Com o pacote Lacuna.RestPkiCore.Client, que inclui o Lacuna.RestPki.Client:
var client = new RestPkiClient("https://sua-instancia.exemplo.com.br/", "SUA_CHAVE_DE_API");
var explorer = new PadesSignatureExplorer(client) {
Validate = true,
DefaultSignaturePolicyId = StandardPadesSignaturePolicies.AdobeReader,
SecurityContextId = StandardSecurityContexts.PkiBrazilWithGovBrAndENotariado,
};
explorer.SetSignatureFile("documento-assinado.pdf");
var signature = await explorer.OpenAsync();
foreach (var signer in signature.Signers) {
var name = signer.Certificate.SubjectName.CommonName;
if (signer.ValidationResults == null) {
Console.WriteLine($"{name} - não validada");
} else if (signer.ValidationResults.IsValid) {
Console.WriteLine($"{name} - válida");
} else {
Console.WriteLine($"{name} - inválida");
Console.WriteLine(signer.ValidationResults);
}
}
REST
curl -X POST "https://sua-instancia.exemplo.com.br/Api/PadesSignatures/Open" \
-H "Authorization: Bearer SUA_CHAVE_DE_API" \
-H "Content-Type: application/json" \
-d '{
"file": { "content": "<PDF em Base64>", "mimeType": "application/pdf" },
"validate": true,
"defaultSignaturePolicyId": "aaed831b-fa9d-4732-82fc-8d25f2c16c57",
"securityContextId": "4bf4409f-db45-4aab-91bf-2c73930ca556"
}'
Cada signatário volta com o próprio resultado de validação. Um signatário cujo certificado não termina em nenhuma das três raízes falha com
CertificateChainRootNotTrusted, sem afetar os outros.
Validar apenas uma hierarquia
Para conferir só as assinaturas de uma hierarquia, use um contexto que confie apenas nela, como GovBR
(5d323217-c031-4eed-9001-1cd82d86a8b5) ou PkiBrazil (201856ce-273c-4058-a872-8937bd547d36), mantendo a política. Com o GovBR, as
assinaturas gov.br passam, e as da ICP-Brasil do mesmo PDF voltam com CertificateChainRootNotTrusted. Isso é o esperado: o contexto não
confia nelas.
Para separar as assinaturas por hierarquia em uma única chamada, use o contexto que confia em todas e olhe o emissor do certificado de cada signatário.
Exigir o padrão PAdES da ICP-Brasil
Para aceitar apenas assinaturas que sigam as políticas AD-RB ou AD-RT da ICP-Brasil, liste-as em acceptableExplicitPolicies e não informe
defaultSignaturePolicyId. Uma assinatura feita no Adobe, que não declara política, falha.
var explorer = new PadesSignatureExplorer(client) {
Validate = true,
AcceptableExplicitPolicies = SignaturePolicyCatalog.GetPkiBrazilPades(),
SecurityContextId = StandardSecurityContexts.PkiBrazil,
};
Na API REST, envie "acceptableExplicitPolicies": ["531d5012-4c0d-4b6f-89e8-ebdcc605d7c2", "10f0d9a5-a0a9-42e9-9523-e181ce05a25b"].
Assinar no formato do Adobe
Para gerar uma assinatura no formato do Adobe, sem dados de LTV, inicie a assinatura PAdES com a política Adobe Reader e um contexto de segurança:
var starter = new PadesSignatureStarter(client) {
SignaturePolicyId = StandardPadesSignaturePolicies.AdobeReader,
SecurityContextId = StandardSecurityContexts.PkiBrazil,
};
O resto do fluxo é o de uma assinatura PAdES do Rest PKI (veja Usando o Rest PKI em .NET). Prefira a política PAdES básica ou a AD-RB, a menos que um sistema exija o formato do Adobe.
Erros comuns
| Erro | Causa | O que fazer |
|---|---|---|
SecurityContextRequired | A política não confia em nenhuma raiz (Basic, BasicWithoutLtv, AdobeReader) e a chamada não informou securityContextId | Informe o contexto de segurança |
InvalidRequest (implicit policy) | Uma política implícita, como a Adobe Reader, foi passada em acceptableExplicitPolicies | Passe-a em defaultSignaturePolicyId |
SignaturePolicyNotFound | O ID não é de uma política que o servidor aceita, como a AD-RC ou a AD-RA para PDF | Use uma política da tabela |
RequiredSignedAttributeMissing (signing-certificate) | A assinatura não segue o PAdES, como as feitas no Adobe Acrobat | Valide com a política Adobe Reader |
CertificateChainRootNotTrusted | O certificado não termina em uma raiz do contexto de segurança | Use um contexto que confie na hierarquia do certificado |
A validação cobre apenas os primeiros signatários de cada arquivo (10 por padrão; veja Inspeção de assinaturas). Os demais voltam sem resultado de validação. E um arquivo assinado na própria instância volta como foi guardado na assinatura, sem nova validação: o contexto e a política da chamada não são usados.
No Rest PKI
No Rest PKI, a relação é a mesma, com estas diferenças:
- A política Adobe Reader serve apenas para validar.
- Os contextos de segurança padrão são só
PkiBrazil,PkiItaly,WindowsServereLacunaTest, sem os do gov.br e do e-Notariado.