Pular para o conteúdo principal

Integração do Web PKI com o Rest PKI

Com o Rest PKI, o seu backend nunca lida com os dados a assinar: ele inicia a assinatura no Rest PKI e recebe um token, a sua página passa esse token ao signWithRestPki() do Web PKI, e o Web PKI troca os dados da assinatura diretamente com o Rest PKI. Depois, o seu backend finaliza a assinatura com o mesmo token e recebe o documento assinado. A autenticação com certificado funciona da mesma forma.

O Rest PKI Core também atende essas APIs do Rest PKI, então a mesma página funciona com ele, desde que saiba onde está a instância (veja O endereço do Rest PKI). O Rest PKI Core tem ainda APIs mais novas, que assinam com o Web PKI de outras formas: veja Com as APIs mais novas do Rest PKI Core.

observação

O Rest PKI é um produto legado: continua recebendo correções de bugs e de segurança, mas novas integrações em nuvem devem usar o Rest PKI Core.

Como funciona​

#QuemO quê
1Seu backend → Rest PKIInicia a assinatura (por exemplo, PadesSignatureStarter.StartWithWebPkiAsync() em .NET), autenticado com o seu access token ou API key. O Rest PKI devolve um token.
2Seu backend → páginaMostra a página de assinatura com o token.
3PáginaChama o init(), lista os certificados do usuário com o listCertificates() e, quando o usuário escolhe um, chama o signWithRestPki() com o token e o thumbprint do certificado.
4Web PKI → Rest PKIA partir do computador do usuário, obtém a assinatura pendente (GET Api/PendingSignatures/{token}) e envia o certificado (POST Api/PendingSignatures/{token}/Certificate). O Rest PKI valida o certificado com o contexto de segurança da assinatura e devolve o hash a assinar.
5Web PKI → Rest PKIAssina o hash com a chave privada do certificado e envia a assinatura (POST Api/PendingSignatures/{token}).
6Página → seu backend → Rest PKIA página envia o token ao seu backend, que finaliza a assinatura (por exemplo, PadesSignatureFinisher2.FinishAsync()) e recebe o documento assinado e o certificado do signatário.

Ou seja:

  • O seu access token fica no seu servidor. A página só vê o token daquela assinatura, que vale uma única vez.
  • As rotas que o Web PKI chama não exigem access token e aceitam chamadas de qualquer origem: o token identifica a assinatura.
  • O computador do usuário precisa acessar o Rest PKI, não só o seu servidor. Veja Requisitos de rede.
  • Se o Rest PKI não aceitar o certificado (por exemplo, porque o contexto de segurança não confia nele), o erro volta para a página, no signWithRestPki().

O código da página​

Inicialize o Web PKI, liste os certificados e, quando o usuário clicar em Assinar, chame o signWithRestPki() com o token que o seu backend colocou na página. Quando a chamada terminar, envie o token de volta ao seu backend:

var pki = new LacunaWebPKI(webPkiLicense); // dispensável com o Rest PKI em nuvem, veja "Licença" abaixo

pki.init({
restPkiUrl: restPkiUrl, // só para um Rest PKI on-premises ou o Rest PKI Core, veja abaixo
ready: loadCertificates,
defaultFail: onWebPkiFail
});

function loadCertificates() {
pki.listCertificates({ selectId: 'certificateSelect' });
}

function sign() {
pki.signWithRestPki({
token: token, // devolvido pelo Rest PKI quando o seu backend iniciou a assinatura
thumbprint: document.getElementById('certificateSelect').value
}).success(function () {
document.getElementById('signForm').submit(); // o seu backend finaliza a assinatura com o token
});
}

function onWebPkiFail(ex) {
alert(ex.userMessage + ' (' + ex.code + ')');
}

Os exemplos têm o código do backend em cada linguagem, e você pode testar a página no JSFiddle.

O endereço do Rest PKI​

O Web PKI precisa saber qual instância do Rest PKI chamar. Informe-a na opção restPkiUrl do init():

Rest PKIrestPkiUrl
Rest PKI em nuvem (https://pki.rest)Não informe
Rest PKI on-premisesO endereço da sua instância, como 'https://restpki.suaempresa.com.br/'
Rest PKI Core, em nuvem ou on-premisesO endpoint da sua instância, como 'https://core.pki.rest/'
pki.init({
restPkiUrl: 'https://restpki.suaempresa.com.br/',
ready: onWebPkiReady
});

Sem o restPkiUrl, o Web PKI acessa a instância em nuvem pela URL https://restpki.lacunasoftware.com/, um endereço alternativo de https://pki.rest que, por ser mais convencional, tem uma chance menor de ser bloqueado pelos firewalls das redes dos usuários.

observação

Se o Web PKI não for utilizado com o Rest PKI, o restPkiUrl é desnecessário.

Requisitos de rede​

Como o Web PKI chama o Rest PKI a partir do computador do usuário:

  • Com o Rest PKI em nuvem, as redes dos usuários precisam liberar o domínio restpki.lacunasoftware.com em HTTPS.
  • Com uma instância própria (Rest PKI on-premises ou Rest PKI Core), ela precisa ser acessível a partir dos computadores dos usuários, não só do seu servidor. Para evitar bloqueios, o endereço dela deve:
    • usar um nome de host, não um endereço IP;
    • usar HTTPS com um certificado SSL válido, emitido por uma Autoridade Certificadora em que os sistemas operacionais confiam por padrão (com um certificado inválido, as chamadas falham sem mensagem de erro);
    • usar uma porta padrão (443).

Para verificar, abra /Api/System/Info da instância em um navegador no computador do usuário, como https://restpki.lacunasoftware.com/Api/System/Info. Veja Erro "Could not get pending signature".

Licença​

Rest PKILicença do Web PKI
Rest PKI em nuvem (https://pki.rest)Não é necessária, nem em produção
Rest PKI on-premisesNecessária fora do localhost
Rest PKI Core, inclusive em nuvem (core.pki.rest)Necessária fora do localhost

Veja Licenciamento.

Teste no JSFiddle​

O exemplo abaixo é a página de uma assinatura do Rest PKI: cole um token, escolha um certificado e assine. Para obter um token sem escrever um backend, inicie uma assinatura CAdES do texto "Hello, World!" com o curl, usando o seu access token do Rest PKI:

curl -X POST https://pki.rest/Api/CadesSignatures \
-H "Authorization: Bearer SEU_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"contentToSign": "SGVsbG8sIFdvcmxkIQ==", "signaturePolicyId": "a4522485-c9e5-46c3-950b-0d6e951e17d1", "securityContextId": "803517ad-3bbc-4169-b085-60053a8f6dbf"}'

A resposta traz o token. A política é a CAdES-BES, e o contexto de segurança, Lacuna Test PKI, aceita também os certificados de teste, então você pode assinar com um deles. Em seguida, abra o exemplo, cole o token e clique em Sign with Rest PKI:

Depois que o Web PKI assinar, finalize a assinatura para obter o CMS (arquivo .p7s):

curl -X POST https://pki.rest/Api/CadesSignatures/O_TOKEN/Finalize \
-H "Authorization: Bearer SEU_ACCESS_TOKEN" \
-d ""

A resposta traz a assinatura em Base64 em cms e o certificado do signatário em certificate.

O código do exemplo está em demo.html, demo.js e demo.css. Para testá-lo com a sua própria instância do Rest PKI ou com o Rest PKI Core, defina o restPkiUrl no início do JavaScript e use o endereço e as credenciais dessa instância (uma API key, no Rest PKI Core) nas chamadas do curl.

Erros​

Além dos outros erros do Web PKI, o signWithRestPki() pode falhar com:

CódigoSignificado
rest_pki_get_pending_signatureO Web PKI não conseguiu obter a assinatura pendente do Rest PKI. Em geral, o Web PKI não consegue acessar a instância: verifique o restPkiUrl e os requisitos de rede. Veja Erro "Could not get pending signature".
rest_pki_post_signatureO Web PKI não conseguiu enviar a assinatura ao Rest PKI.
rest_pki_invalid_certificateO Rest PKI não aceitou o certificado escolhido, por exemplo porque o contexto de segurança da assinatura não confia nele.

Um token vale uma única vez: para assinar de novo, inicie uma nova assinatura no seu backend.

Com as APIs mais novas do Rest PKI Core​

O Rest PKI Core continua atendendo as APIs do Rest PKI que o signWithRestPki() usa e acrescenta APIs mais novas, que usam o Web PKI de outra forma:

  • Sessões de assinatura: você redireciona o usuário para uma página de assinatura hospedada pelo Rest PKI Core, que usa o próprio Web PKI. As suas páginas não têm código do Web PKI.
  • Assinaturas em duas etapas: o seu backend prepara a assinatura, a sua página assina o hash com o signHash() do Web PKI, e o seu backend conclui a assinatura.

Veja Migração do Rest PKI para o Rest PKI Core.

Exemplos​

Os exemplos do Rest PKI, em cada linguagem abaixo, assinam com o signWithRestPki(). Veja também o Rest PKI.

Veja também​

Ver em Markdown