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
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 │
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",
},
});
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
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);
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}");
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);
| 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) |