6.6 KiB
SDK Web JavaScript (@cybercore/signer-sdk)
Manual de Integração de Aplicações Web Modernas com o Agente Desktop CyberCore Signer
O @cybercore/signer-sdk é a biblioteca cliente oficial em JavaScript (TypeScript ready) desenvolvida para permitir que aplicações web modernas (React, Next.js, Vue, Angular ou JavaScript nativo) se comuniquem com o agente desktop CyberCore Signer através do protocolo local CCSP/1.
1. Instalação e Configuração
1.1 Instalação via Gerenciador de Pacotes
npm install @cybercore/signer-sdk
# ou
yarn add @cybercore/signer-sdk
# ou
pnpm add @cybercore/signer-sdk
1.2 Inicialização do Cliente
import { CyberCoreSigner } from '@cybercore/signer-sdk';
const signer = new CyberCoreSigner({
applicationName: 'Portal Meu Negócio', // Nome exibido no diálogo nativo do usuário
port: 21325, // Porta padrão do agente local (opcional)
timeoutMs: 30000 // Timeout padrão para operações (opcional)
});
2. Métodos da API
2.1 Verificação de Disponibilidade e Conexão
isInstalled(timeoutMs = 2000): Promise<boolean>
Testa de forma rápida e silenciosa se o agente desktop está ativo na máquina do usuário.
const disponivel = await signer.isInstalled();
if (!disponivel) {
alert('O CyberCore Signer não foi detectado em sua máquina. Por favor, instale o aplicativo para continuar.');
}
connect(): Promise<boolean>
Inicia o handshake de autorização com o agente. Se a aplicação ainda não foi homologada pelo usuário, abre um diálogo nativo na tela do computador para autorização expressa.
const autorizado = await signer.connect();
if (!autorizado) {
console.warn('O usuário recusou a autorização da aplicação.');
}
2.2 Descoberta de Certificados Digitais
getCertificates(): Promise<Array<CertificateInfo>>
Retorna a lista de certificados digitais válidos e disponíveis na máquina (A1 importados e A3 conectados via USB).
const certificados = await signer.getCertificates();
certificados.forEach(cert => {
console.log(`[${cert.type}] ${cert.common_name}`);
console.log(`Titular: ${cert.subject_dn}`);
console.log(`Validade até: ${cert.valid_to}`);
console.log(`CPF/CNPJ: ${cert.cpf || cert.cnpj}`);
});
2.3 Operações de Assinatura Digital
sign(options): Promise<SignatureResult>
Assina o hash SHA-256 (digest) de qualquer informação. A chave privada nunca sai do computador e apenas o digest é assinado.
const resultado = await signer.sign({
certificateId: 'win-4340656a',
digest: '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', // Hash SHA-256 em Base64
documentName: 'contrato_prestacao_servicos.pdf',
documentType: 'PDF'
});
console.log('Assinatura gerada (Base64):', resultado.signature);
console.log('Certificado do signatário:', resultado.certificate);
console.log('Cadeia de certificação:', resultado.certificate_chain);
signPdf(file, options): Promise<SignatureResult>
Calcula o hash do documento PDF no próprio navegador e solicita a assinatura ao CyberCore Signer.
const inputElement = document.getElementById('arquivo-pdf');
const arquivoPdf = inputElement.files[0];
const resultadoPdf = await signer.signPdf(arquivoPdf, {
certificateId: certificados[0].id
});
console.log('PDF assinado digitalmente com sucesso!');
signXml(xmlContent, options): Promise<SignatureResult>
Assina o hash de documentos XML ou notas fiscais eletrônicas (NF-e, CT-e, MDF-e, XAdES). Aceita string com o XML ou arquivo File/Blob.
const xmlString = '<infNFe Id="NFe3524...">...</infNFe>';
const resultadoXml = await signer.signXml(xmlString, {
certificateId: certificados[0].id,
documentName: 'nfe-3524.xml'
});
signFile(file, options): Promise<SignatureResult>
Assina arquivos genéricos de qualquer formato (ZIP, DOCX, XLSX, imagens, binários).
const fileInput = document.getElementById('input-qualquer-arquivo');
const resultadoArquivo = await signer.signFile(fileInput.files[0], {
certificateId: certificados[0].id
});
2.4 Autenticação e Login Digital (Challenge-Response)
authenticate(options): Promise<AuthResult>
Realiza o login seguro de um usuário através de seu certificado digital ICP-Brasil. O backend da sua aplicação fornece um desafio único (challenge / nonce) e o CyberCore assina esse desafio.
// 1. Obter desafio único do backend da sua aplicação
const { challenge } = await fetch('/api/auth/challenge').then(res => res.json());
// 2. Solicitar assinatura do desafio ao CyberCore Signer
const authResult = await signer.authenticate({
certificateId: certificados[0].id,
challenge: challenge
});
// 3. Enviar a assinatura e o certificado para o backend validar e autenticar a sessão
const response = await fetch('/api/auth/validate-login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
challenge: authResult.challenge,
signature: authResult.signature,
certificate: authResult.certificate
})
});
if (response.ok) {
console.log(`Login aprovado para: ${authResult.subjectName} (${authResult.subjectCpfCnpj})`);
window.location.href = '/dashboard';
}
3. Tratamento Estruturado de Erros
O SDK expõe classes de erro dedicadas que herdam de CyberCoreError, permitindo tratar cenários de forma elegante na interface:
import {
UserCancelledError,
PinIncorrectError,
TokenNotFoundError,
CertificateNotFoundError,
CertificateExpiredError
} from '@cybercore/signer-sdk/errors';
try {
const res = await signer.sign({
certificateId: certId,
digest: documentoDigest
});
} catch (error) {
if (error instanceof UserCancelledError) {
// Usuário cancelou a assinatura voluntariamente na janela nativa
console.info('Operação cancelada pelo usuário.');
} else if (error instanceof PinIncorrectError) {
// PIN do token A3 incorreto
alert('PIN incorreto! Por favor, digite o PIN correto do seu token.');
} else if (error instanceof TokenNotFoundError) {
// Token USB desconectado
alert('Token não encontrado! Por favor, conecte seu dispositivo USB para assinar.');
} else if (error instanceof CertificateExpiredError) {
// Certificado ultrapassou a data de validade
alert('O certificado selecionado expirou. Entre em contato com sua autoridade certificadora.');
} else {
// Demais falhas
console.error('Falha na operação com o CyberCore Signer:', error);
}
}