ShieldSign PKIDocumentação

SDK JavaScript

Extensão, certificados A1 e A3, filtros e o cliente da API para Node.

O SDK JavaScript (@shieldsign/sdk) tem duas partes, que rodam em lugares diferentes:

Parte Roda em Para quê
ExtensionSigner, A3Signer, A1Signer e os filtros Navegador Listar certificados, assinar com a extensão ou com um .pfx. Nunca usa chave de API.
ShieldSignClient Node ou outro back-end JavaScript Chamar a API com a chave de API. Não use no navegador.

Instalação#

Baixe o SDK na página de Downloads. Há dois formatos:

  • Um arquivo só (shieldsign-sdk-<versão>.browser.mjs): copie para a pasta de arquivos públicos do seu sistema e importe.
  • Pacote npm (shieldsign-sdk-<versão>.tgz): para quem usa bundler. npm install ./shieldsign-sdk-<versão>.tgz.
<script type="module">
  import { ExtensionSigner } from "/assets/shieldsign-sdk-0.3.0.browser.mjs";
</script>

Com bundler: import { ExtensionSigner } from "@shieldsign/sdk";

No navegador#

Escolher quem assina#

import { A3Signer, A1Signer, ExtensionSigner } from "@shieldsign/sdk";

let signer;
if (await ExtensionSigner.isAvailable()) {
  const [cert] = await ExtensionSigner.listCertificates();   // normalmente você mostra a lista e o usuário escolhe
  signer = new A3Signer(cert.thumbprint);                    // token A3, cartão ou certificado do repositório do Windows
} else {
  signer = await A1Signer.fromPfx(bytesDoPfx, senha);        // A1 em arquivo: sem instalar nada
}

Todo signer tem certificate() (o DER, como Uint8Array), sign(dados, algoritmo) e, no caso de A3Signer, signMany(lista, algoritmo), que assina vários documentos com uma só aprovação e um só PIN.

O fluxo completo, ligando o signer ao seu servidor, está em Assinar PDFs no seu sistema.

A lista de certificados#

Cada item de ExtensionSigner.listCertificates() traz:

Campo O que é
thumbprint SHA-256 do certificado: identificador estável.
subjectDn, issuerDn DN em RFC 4514 (CN=NOME:123,OU=…,O=ICP-Brasil,C=BR). É o mesmo formato que a API devolve e que acceptableIssuers aceita.
subjectCn, issuerCn Só o Common Name, pronto para a tela; o do titular já sem o :CPF/CNPJ.
subjectName, issuerName Texto para exibir. Não compare por eles.
serialNumber, notBefore, notAfter, keyUsage Os dados do certificado.
pkiBrazil CPF, CNPJ e demais campos ICP-Brasil (veja Identidade do certificado). Sempre existe; fora da ICP-Brasil, tudo null.
keyStorage "token", "file", "cloud" ou "unknown". Informativo: é uma heurística sobre o provedor de chaves do Windows. Serve para a tela, nunca para segurança.
icpBrasil Heurística: o emissor tem O=ICP-Brasil. Não valida a cadeia: quem valida é a API.
isTest Heurística: AC de teste conhecida pelo nome, ou validade absurdamente longa.
sources Onde está a chave (pkcs11 para token, os para o repositório do sistema).

A lista já não traz raízes nem intermediárias, só o certificado do titular.

A tela é só organização

No navegador, filtrar por CPF ou emissor organiza a interface: não é controle de acesso. Para regra de negócio e auditoria, use o que a API devolve no prepare e no complete.

Filtros prontos#

Os filtros são combináveis e a lista já volta ordenada, com a validade mais distante primeiro:

import { ExtensionSigner, certFilters as f, filterCertificates } from "@shieldsign/sdk";

const certs = filterCertificates(
  await ExtensionSigner.listCertificates(),
  f.validNow(),          // dentro da validade
  f.canSign(),           // pode assinar documentos
  f.icpBrasilChain(),    // emissor O=ICP-Brasil
  f.notTest(),           // esconde os de teste
  f.eCpf(),              // ou f.eCnpj(), f.cpf("111.444.777-35"), f.cnpj("…"), f.issuer("AC Soluti")
);

Exemplos com pkiBrazil:

const certs = await ExtensionSigner.listCertificates();
const soEcnpj = certs.filter((c) => c.pkiBrazil.kind === "pj");
const daEmpresa = certs.filter((c) => c.pkiBrazil.cnpj === "11222333000181");

Erros#

import { ExtensionError } from "@shieldsign/sdk";

try {
  await assinar(arquivos, signer);
} catch (e) {
  if (e instanceof ExtensionError) {
    // e.code: extension_not_found | user_cancelled | pin_incorrect | pin_locked | timeout | ...
  }
}

A tabela completa dos códigos está em Extensão e agente.

No servidor Node: ShieldSignClient#

Para back-ends JavaScript. Ele faz o fluxo inteiro (iniciar, preparar, assinar com o signer que você passar, concluir e baixar), repetindo o complete com a mesma Idempotency-Key em caso de falha de rede.

import { ShieldSignClient, A1Signer } from "@shieldsign/sdk";

const client = new ShieldSignClient({
  apiUrl: "https://api.pki.shieldsign.com.br",
  apiKey: process.env.SHIELDSIGN_KEY,
  // completeRetries: 2, retryDelayMs: 400   // padrões
});

const r = await client.signPades({
  pdf: new Uint8Array(await readFile("contrato.pdf")),
  signer: await A1Signer.fromPfx(pfxBytes, senha),
  signaturePolicyId: "pades-icpbrasil-ad-rb",
  securityContextId: "icp-brasil",
});
// r.signedPdf (Uint8Array), r.certificate, r.warnings
Método O que faz
signPades(opções) Assina um PDF. Aceita acceptableIssuers, visualRepresentation, signatureFieldName e beforeSign.
signPadesBatch(opções) Assina vários PDFs com uma só aprovação.
verifyPades({ pdf, securityContextId }) Verifica as assinaturas de um PDF (Verificar assinaturas).
authenticateWithCertificate({ signer, origin, securityContextId }) Login por certificado (Login com certificado).

beforeSign(certificado) roda depois do prepare e antes do PIN, com a identidade já validada pela API. Lance um erro para recusar (por exemplo, CPF diferente do esperado): a sessão é descartada e nada é assinado nem cobrado.

Os erros da API viram ShieldSignApiError, com status, code (estável) e, nas recusas de certificado, reason. Veja Erros.

ShieldSign PKI · Shield Certificadora · contato@shieldcertificadora.com.br · Privacidade