Assine seu primeiro documento em 5 minutos

Um guia completo desde um projeto VCL novo até um envelope XAdES assinado. Funciona com Delphi 7 ao RAD Studio 13 e C++Builder.

Delphi 7 – RAD Studio 13
C++ Builder
VeriFactu Profile

Antes de começar

Apenas duas coisas — sgcSign instalado na IDE e um certificado PFX para assinar.

Você vai precisar

  • sgcSign instalado na sua IDE — veja a página de download.
  • Um arquivo de certificado PFX com sua senha (qualquer arquivo X.509 PKCS#12 funciona).
  • Delphi 7 ao RAD Studio 13, ou qualquer versão do C++Builder. Windows 32-bit e 64-bit são ambos suportados.
  • Sem dependências externas — o sgcSign usa Windows CNG/BCrypt para criptografia e WinHTTP para chamadas de rede.
make-test-cert.sh
# No PFX yet? Generate a self-signed test cert with OpenSSL:
openssl req -x509 -newkey rsa:2048 \
  -keyout key.pem -out cert.pem \
  -days 365 -nodes \
  -subj "/CN=sgcSign Test"

openssl pkcs12 -export \
  -inkey key.pem -in cert.pem \
  -out test.pfx \
  -password pass:secret

# Now you have test.pfx with password "secret".

Criar um Novo Projeto

Crie um aplicativo VCL Forms na sua IDE. Solte dois memos e um botão no formulário — essa é a interface completa.

Layout do formulário

  • memoXMLTMemo, cole seu XML não assinado aqui.
  • memoSignedTMemo, o XML assinado aparece aqui após o clique no botão.
  • btnSignTButton, conectado ao manipulador OnClick no passo 2.
  • Nenhum componente em tempo de design necessário — tudo é criado em código.
Unit1.dfm
object Form1: TForm1
  Caption = 'sgcSign Início rápido'
  ClientWidth  = 800
  ClientHeight = 600

  object memoXML: TMemo
    Left = 8
    Top  = 8
    Width  = 784
    Height = 240
  end

  object memoSigned: TMemo
    Left = 8
    Top  = 288
    Width  = 784
    Height = 300
  end

  object btnSign: TButton
    Left = 8
    Top  = 256
    Caption = 'Sign XML'
  end
end

Adicionar o Código de Assinatura

Carregue um provedor PFX, aponte um assinador de documentos para ele com o perfil VeriFactu e chame SignXML.

Delphi

  • TsgcPFXKeyProvider importa o .pfx via Windows CNG — assinatura SHA-256 moderna funciona independentemente do CSP original.
  • TsgcDocumentSigner escolhe o nível XAdES correto com base no perfil.
  • spVeriFactu seleciona o VeriFactu da AEAT espanhola — XAdES-EPES, B-B, RSA-SHA256, C14N exclusivo.
  • Troque a constante por qualquer um dos 21 perfis de país — veja Perfis de País.
Unit1.pas
procedure TForm1.btnSignClick(Sender: TObject);
var
  vKeyProvider: TsgcPFXKeyProvider;
  vSigner: TsgcDocumentSigner;
begin
  vKeyProvider := TsgcPFXKeyProvider.Create(nil);
  try
    vKeyProvider.FileName := 'certificate.pfx';
    vKeyProvider.Password := 'secret';
    vKeyProvider.LoadFromFile;

    vSigner := TsgcDocumentSigner.Create(nil);
    try
      vSigner.KeyProvider := vKeyProvider;
      vSigner.Profile := spVeriFactu;
      memoSigned.Text := vSigner.SignXML(memoXML.Text);
    finally
      vSigner.Free;
    end;
  finally
    vKeyProvider.Free;
  end;
end;

C++ Builder

  • Mesma estrutura, mesmas classes, mesmos nomes de propriedades — o wrapper C++ é uma portabilidade 1:1 da API Delphi.
  • O bloco __finally garante que os provedores sejam liberados mesmo se a assinatura lançar uma exceção.
  • UnicodeString é usado de ponta a ponta — sem conversão ANSI/UTF-8 com que se preocupar.
Unit1.cpp
void __fastcall TForm1::btnSignClick(TObject *Sender)
{
  TsgcPFXKeyProvider *vKeyProvider = new TsgcPFXKeyProvider(NULL);
  try {
    vKeyProvider->FileName = "certificate.pfx";
    vKeyProvider->Password = "secret";
    vKeyProvider->LoadFromFile();

    TsgcDocumentSigner *vSigner = new TsgcDocumentSigner(NULL);
    try {
      vSigner->KeyProvider = vKeyProvider;
      vSigner->Profile = spVeriFactu;
      memoSigned->Text = vSigner->SignXML(memoXML->Text);
    } __finally {
      delete vSigner;
    }
  } __finally {
    delete vKeyProvider;
  }
}

Adicionar as Units Necessárias

Duas units na sua cláusula uses — o provedor PFX e o assinador de documentos.

Cláusula uses no Delphi

Cada provedor de chave reside em sua própria unit para que você pague apenas pelo que referencia. sgcSign_DocumentSigner traz a camada de roteamento que escolhe XAdES, PAdES ou CAdES com base na entrada.

Unit1.pas
uses
  Classes, SysUtils, Forms, StdCtrls, Controls,
  // sgc
  sgcSign_KeyProvider_PFX,
  sgcSign_DocumentSigner;

Includes do C++Builder

As mesmas units, expostas como cabeçalhos .hpp. O linker do C++Builder resolve as bibliotecas estáticas subjacentes automaticamente.

Unit1.cpp
#include "sgcSign_KeyProvider_PFX.hpp"
#include "sgcSign_DocumentSigner.hpp"

Executar e Testar

Pressione F9, cole uma nota fiscal no memo superior, clique em Sign XML. O envelope assinado aparece no memo inferior.

Compilar e executar

Pressione F9 na IDE. O formulário abre com dois memos e um botão. Sem exceções, sem units faltando.

Colar a entrada

Solte qualquer XML de nota fiscal (ou qualquer XML bem formado) em memoXML. O assinador o normaliza para UTF-8 internamente.

Verificar o resultado

memoSigned agora contém seu XML com um elemento <ds:Signature> envelopado anexado. Salve-o, passe-o por qualquer verificador XAdES — ou use TsgcSignatureVerifier diretamente.

Unicode e a Sobrecarga WideString

No Delphi 7, string é AnsiString. Use as sobrecargas WideString para transmitir caracteres poloneses, cirílicos ou gregos sem perda.

O problema

No Delphi 7, a sobrecarga string passa pelo ACP do sistema. Diacríticos em 'Jarosław' só são transmitidos corretamente quando o ACP do sistema é CP1250. Se o ACP for CP1252, os caracteres ficam corrompidos no XML assinado.

As sobrecargas WideString ignoram o ACP completamente — UTF-16 para UTF-8 via WideCharToMultiByte com CP_UTF8. No Delphi 2009+ ambas as sobrecargas são equivalentes; UnicodeString já é UTF-16.

d7-unicode.pas
var
  Doc: IXMLDocument;       // MSXML6
  XML, Signed: WideString; // = MSXML6 DOMString
  Sign: TsgcXAdESSigner;
begin
  Doc.SaveToXML(XML);            // WideString out, no ACP step
  Signed := Sign.SignXML(XML);   // resolves to WideString overload
  // Polish, Cyrillic, Greek round-trip losslessly
end;

UTC por Padrão

Todos os carimbos de hora X.509 / CRL / OCSP / TSA são armazenados como valores UTC TDateTime, correspondendo às especificações ASN.1 subjacentes.

Exibir no horário local

Para exibições ao usuário final, use as propriedades *Local em cada componente (ex.: vCert.NotAfterLocal) ou converta manualmente com sgcUTCToLocal da unit sgcSign_Time.

Isso corresponde à RFC 5280 (X.509), RFC 3161 (TSA) e RFC 6960 (OCSP), que especificam UTC. O helper sgcUTCNow retorna o TDateTime UTC atual para código que precisa comparar carimbos de hora.

time-zones.pas
uses sgcSign_Time;

// Display certificate validity in local time
Memo1.Lines.Add('Cert expires: ' +
                DateTimeToStr(vCert.NotAfterLocal));
Memo1.Lines.Add('Now (UTC):    ' +
                DateTimeToStr(sgcUTCNow));

// Or convert manually
vLocal := sgcUTCToLocal(vCert.NotAfter);

Para Onde Ir a Partir Daqui

XAdES é apenas o começo. PAdES, CAdES, perfis, provedores de chave e o servidor centralizado estão todos a um clique.

Visão Geral de Recursos

Conheça toda a superfície da API XAdES, PAdES, CAdES e a infraestrutura de suporte de timestamp + OCSP.

Saiba mais →

21 Perfis de País

VeriFactu, FatturaPA, KSeF, FACTUR-X, mais 9 perfis de contratos de trabalho da UE. Troca de jurisdição em uma linha.

Saiba mais →

10 Provedores de Chave

PFX, PEM, repositório Windows, PKCS#11, Azure Trusted Signing, AWS KMS, Google KMS, Vault, Certum, CSC v2.

Saiba mais →

sgcSign Server

Centralize a assinatura em todo o farm de build. API REST, administração web, GitHub Actions, Azure DevOps, Jenkins, Docker.

Saiba mais →

Pronto para Produção?

Baixe a versão de avaliação, distribua um binário assinado hoje, licencie o sgcSign quando estiver satisfeito.