Guias de Desenvolvimento

Política e Conformidade

Signing Sessions

Guias dos SDKs

Certificado Digital A1 (DIGITAL_CERTIFICATE)

Assinatura com certificado digital ICP-Brasil tipo A1. A chave privada nunca sai do lado do cliente — a API fornece o hash a ser assinado, o cliente assina localmente e envia a assinatura de volta.

Etapas geradas: DIGITAL_SIGN_A1


Fluxo Criptográfico

Cliente                                    API SignDocsBrasil
  │                                              │
  │  1. certificateChainPems ──────────────────► │  Valida cadeia
  │                                              │  Prepara documento
  │  ◄──────────────────── 2. hashToSign         │
  │                                              │
  │  3. Assina hash localmente                   │
  │     (chave privada NUNCA sai do cliente)      │
  │                                              │
  │  4. rawSignatureBase64 ────────────────────► │  Embute no documento
  │                                              │  Gera CMS/PKCS#7
  │  ◄──────────────────── 5. Documento assinado  │

Passo 1: Criar transação

Use o perfil DIGITAL_CERTIFICATE. Opcionalmente, configure metadados da assinatura digital.

const tx = await client.transactions.create({
  purpose: 'DOCUMENT_SIGNATURE',
  policy: { profile: 'DIGITAL_CERTIFICATE' },
  signer: {
    name: 'João Silva',
    userExternalId: 'user-001',
    cpf: '12345678900',
  },
  document: {
    content: documentBase64,
    filename: 'contrato.pdf',
  },
  digitalSignature: {
    signatureFieldName: 'Assinatura1',
    signatureReason: 'Aprovação do contrato',
    signatureLocation: 'São Paulo, SP',
  },
});
tx = client.transactions.create(CreateTransactionRequest(
    purpose='DOCUMENT_SIGNATURE',
    policy=Policy(profile='DIGITAL_CERTIFICATE'),
    signer=Signer(name='João Silva', user_external_id='user-001', cpf='12345678900'),
    document=InlineDocument(content=document_base64, filename='contrato.pdf'),
    digital_signature=DigitalSignatureMetadata(
        signature_field_name='Assinatura1',
        signature_reason='Aprovação do contrato',
        signature_location='São Paulo, SP',
    ),
))
tx, _ := client.Transactions.Create(ctx, &signdocs.CreateTransactionRequest{
    Purpose: signdocs.TransactionPurposeDocumentSignature,
    Policy:  signdocs.Policy{Profile: signdocs.PolicyProfileDigitalCertificate},
    Signer:  signdocs.Signer{Name: "João Silva", UserExternalID: "user-001", CPF: "12345678900"},
    Document: &signdocs.DocumentInline{Content: documentBase64, Filename: "contrato.pdf"},
    DigitalSignature: &signdocs.DigitalSignatureMetadata{
        SignatureFieldName: "Assinatura1",
        SignatureReason:    "Aprovação do contrato",
        SignatureLocation:  "São Paulo, SP",
    },
})
CreateTransactionRequest request = new CreateTransactionRequest();
request.purpose = "DOCUMENT_SIGNATURE";
request.policy = new Policy("DIGITAL_CERTIFICATE");
request.signer = new Signer("João Silva", null, "user-001");
request.signer.cpf = "12345678900";
request.document = new CreateTransactionRequest.InlineDocument(documentBase64, "contrato.pdf");
request.digitalSignature = new CreateTransactionRequest.DigitalSignatureMetadata();
request.digitalSignature.signatureFieldName = "Assinatura1";
request.digitalSignature.signatureReason = "Aprovação do contrato";
request.digitalSignature.signatureLocation = "São Paulo, SP";

Transaction tx = client.transactions().create(request);
$tx = $client->transactions->create(new CreateTransactionRequest(
    purpose: 'DOCUMENT_SIGNATURE',
    policy: new Policy(profile: 'DIGITAL_CERTIFICATE'),
    signer: new Signer(name: 'João Silva', userExternalId: 'user-001', cpf: '12345678900'),
    document: ['content' => $documentBase64, 'filename' => 'contrato.pdf'],
    digitalSignature: [
        'signatureFieldName' => 'Assinatura1',
        'signatureReason' => 'Aprovação do contrato',
        'signatureLocation' => 'São Paulo, SP',
    ],
));
using SignDocsBrasil.Api;
using SignDocsBrasil.Api.Models;

var client = SignDocsBrasilClient.CreateBuilder()
    .ClientId("your-client-id")
    .ClientSecret("your-client-secret")
    .Build();

var tx = await client.Transactions.CreateAsync(new CreateTransactionRequest
{
    Purpose = "DOCUMENT_SIGNATURE",
    Policy = new Policy { Profile = "DIGITAL_CERTIFICATE" },
    Signer = new Signer { Name = "João Silva", UserExternalId = "user-001", Cpf = "12345678900" },
    Document = new InlineDocument { Content = documentBase64, Filename = "contrato.pdf" },
    DigitalSignature = new DigitalSignatureMetadata
    {
        SignatureFieldName = "Assinatura1",
        SignatureReason = "Aprovação do contrato",
        SignatureLocation = "São Paulo, SP",
    },
});

Passo 2: Preparar assinatura (enviar cadeia de certificados)

Envie a cadeia de certificados PEM (leaf + intermediários). A API valida a cadeia e prepara o hash do documento.

const prep = await client.signing.prepare(tx.transactionId, {
  certificateChainPems: [leafCertPem, intermediateCertPem],
});
console.log(prep.signatureRequestId);  // ID da requisição
console.log(prep.hashToSign);          // Hash a ser assinado (hex)
console.log(prep.hashAlgorithm);       // SHA-256
console.log(prep.signatureAlgorithm);  // RSASSA-PKCS1-v1_5
from signdocs_brasil.models import PrepareSigningRequest

prep = client.signing.prepare(tx.transaction_id, PrepareSigningRequest(
    certificate_chain_pems=[leaf_cert_pem, intermediate_cert_pem],
))
print(prep.signature_request_id)
print(prep.hash_to_sign)
print(prep.hash_algorithm)       # SHA-256
print(prep.signature_algorithm)  # RSASSA-PKCS1-v1_5
prep, _ := client.Signing.Prepare(ctx, tx.TransactionID, &signdocs.PrepareSigningRequest{
    CertificateChainPEMs: []string{leafCertPem, intermediateCertPem},
})
fmt.Println(prep.SignatureRequestID)
fmt.Println(prep.HashToSign)
fmt.Println(prep.HashAlgorithm)      // SHA-256
fmt.Println(prep.SignatureAlgorithm) // RSASSA-PKCS1-v1_5
PrepareSigningResponse prep = client.signing().prepare(tx.transactionId,
    new PrepareSigningRequest(List.of(leafCertPem, intermediateCertPem)));
System.out.println(prep.signatureRequestId);
System.out.println(prep.hashToSign);
System.out.println(prep.hashAlgorithm);      // SHA-256
System.out.println(prep.signatureAlgorithm); // RSASSA-PKCS1-v1_5
$prep = $client->signing->prepare($tx->transactionId, new PrepareSigningRequest(
    certificateChainPems: [$leafCertPem, $intermediateCertPem],
));
echo $prep->signatureRequestId;
echo $prep->hashToSign;
echo $prep->hashAlgorithm;      // SHA-256
echo $prep->signatureAlgorithm; // RSASSA-PKCS1-v1_5
using System.Security.Cryptography.X509Certificates;

var pfxBytes = await File.ReadAllBytesAsync("certificado.pfx");
var cert = new X509Certificate2(pfxBytes, "senha_do_pfx", X509KeyStorageFlags.Exportable);
var leafCertPem = cert.ExportCertificatePem();

var prep = await client.Signing.PrepareAsync(tx.TransactionId, new PrepareSigningRequest
{
    CertificateChainPems = new[] { leafCertPem, intermediateCertPem },
});
Console.WriteLine($"SignatureRequestId: {prep.SignatureRequestId}");
Console.WriteLine($"HashToSign: {prep.HashToSign}");
Console.WriteLine($"HashAlgorithm: {prep.HashAlgorithm}");          // SHA-256
Console.WriteLine($"SignatureAlgorithm: {prep.SignatureAlgorithm}"); // RSASSA-PKCS1-v1_5

Passo 3: Assinar hash localmente

Assine prep.hashToSign com a chave privada do certificado usando RSASSA-PKCS1-v1_5 com SHA-256. Converta o resultado para base64.

A chave privada NUNCA é enviada para a API. Toda a operação criptográfica ocorre no ambiente do cliente.

import crypto from 'crypto';

const sign = crypto.createSign('SHA256');
sign.update(Buffer.from(prep.hashToSign, 'hex'));
const signatureBase64 = sign.sign(privateKeyPem, 'base64');
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
import base64

private_key = serialization.load_pem_private_key(private_key_pem.encode(), password=None)
signature = private_key.sign(
    bytes.fromhex(prep.hash_to_sign),
    padding.PKCS1v15(),
    hashes.SHA256(),
)
signature_base64 = base64.b64encode(signature).decode()
import (
    "crypto"
    "crypto/rand"
    "crypto/rsa"
    "encoding/base64"
    "encoding/hex"
)

hashBytes, _ := hex.DecodeString(prep.HashToSign)
signature, _ := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashBytes)
signatureBase64 := base64.StdEncoding.EncodeToString(signature)
import java.security.Signature;
import java.util.Base64;

byte[] hashBytes = hexToBytes(prep.hashToSign);
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(privateKey);
sig.update(hashBytes);
byte[] signature = sig.sign();
String signatureBase64 = Base64.getEncoder().encodeToString(signature);
$hashBytes = hex2bin($prep->hashToSign);
openssl_sign($hashBytes, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$signatureBase64 = base64_encode($signature);
using System.Security.Cryptography;

var rsa = cert.GetRSAPrivateKey()!;
var hashBytes = Convert.FromHexString(prep.HashToSign);
var signatureBytes = rsa.SignData(hashBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
var signatureBase64 = Convert.ToBase64String(signatureBytes);

Passo 4: Completar assinatura (enviar assinatura raw)

Envie a assinatura base64 de volta para a API. Ela será embutida no documento junto com a cadeia de certificados (PAdES para PDF, CAdES .p7s para demais formatos).

const result = await client.signing.complete(tx.transactionId, {
  signatureRequestId: prep.signatureRequestId,
  rawSignatureBase64: signatureBase64,
});
console.log(result.status); // COMPLETED
console.log(result.result.digitalSignature.certificateSubject);
console.log(result.result.digitalSignature.signedAt);
from signdocs_brasil.models import CompleteSigningRequest

result = client.signing.complete(tx.transaction_id, CompleteSigningRequest(
    signature_request_id=prep.signature_request_id,
    raw_signature_base64=signature_base64,
))
print(result.status)  # COMPLETED
print(result.result.digital_signature.certificate_subject)
result, _ := client.Signing.Complete(ctx, tx.TransactionID, &signdocs.CompleteSigningRequest{
    SignatureRequestID: prep.SignatureRequestID,
    RawSignatureBase64: signatureBase64,
})
fmt.Println(result.Status)
fmt.Println(result.Result.DigitalSignature.CertificateSubject)
CompleteSigningResponse result = client.signing().complete(tx.transactionId,
    new CompleteSigningRequest(prep.signatureRequestId, signatureBase64));
System.out.println(result.status);
System.out.println(result.result.digitalSignature.certificateSubject);
$result = $client->signing->complete($tx->transactionId, new CompleteSigningRequest(
    signatureRequestId: $prep->signatureRequestId,
    rawSignatureBase64: $signatureBase64,
));
echo $result->status;
echo $result->result['digitalSignature']['certificateSubject'];
var result = await client.Signing.CompleteAsync(tx.TransactionId, new CompleteSigningRequest
{
    SignatureRequestId = prep.SignatureRequestId,
    RawSignatureBase64 = signatureBase64,
});
Console.WriteLine($"Status: {result.Status}"); // COMPLETED
Console.WriteLine($"Subject: {result.Result.DigitalSignature.CertificateSubject}");
Console.WriteLine($"SignedAt: {result.Result.DigitalSignature.SignedAt}");

Passo 5: Finalizar transação

const finalized = await client.transactions.finalize(tx.transactionId);
const evidence = await client.evidence.get(tx.transactionId);
const download = await client.documents.download(tx.transactionId);
finalized = client.transactions.finalize(tx.transaction_id)
evidence = client.evidence.get(tx.transaction_id)
download = client.documents.download(tx.transaction_id)
client.Transactions.Finalize(ctx, tx.TransactionID)
evidence, _ := client.Evidence.Get(ctx, tx.TransactionID)
download, _ := client.Documents.Download(ctx, tx.TransactionID)
client.transactions().finalize(tx.transactionId);
Evidence evidence = client.evidence().get(tx.transactionId);
DownloadResponse download = client.documents().download(tx.transactionId);
$client->transactions->finalize($tx->transactionId);
$evidence = $client->evidence->get($tx->transactionId);
$download = $client->documents->download($tx->transactionId);
await client.Transactions.FinalizeAsync(tx.TransactionId);
var evidence = await client.Evidence.GetAsync(tx.TransactionId);
var download = await client.Documents.DownloadAsync(tx.TransactionId);

Campos do resultado da assinatura digital

Campo Descrição
certificateSubject DN do certificado (ex: CN=JOAO SILVA, ...)
certificateSerial Número serial do certificado
certificateIssuer DN da autoridade certificadora
algorithm Algoritmo usado (ex: SHA256withRSA)
signedAt Timestamp da assinatura (ISO 8601)
signedPdfHash Hash SHA-256 do documento assinado (PDF). Para formatos genéricos, use signedP7sHash.
signatureFieldName Nome do campo de assinatura no PDF (apenas PAdES)