5분 안에 첫 번째 문서에 서명하기

새 VCL 프로젝트에서 서명된 XAdES 봉투까지의 완전한 안내예요. Delphi 7부터 RAD Studio 13 및 C++Builder에서 작동해요.

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

시작하기 전에

두 가지만 필요해요 — IDE에 sgcSign이 설치되어 있고, 서명에 사용할 PFX 인증서가 있으면 돼요.

필요한 것들

  • sgcSign이 IDE에 설치되어 있어야 해요 — 다운로드 페이지를 참고하세요.
  • PFX 인증서 파일과 비밀번호(X.509 PKCS#12 파일이면 모두 사용 가능해요).
  • Delphi 7부터 RAD Studio 13까지, 또는 C++ Builder의 모든 버전. 32비트와 64비트 Windows를 모두 지원해요.
  • 외부 의존성 없음 — sgcSign은 암호화를 위해 Windows CNG/BCrypt를, 네트워크 호출을 위해 WinHTTP를 사용해요.
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".

새 프로젝트 만들기

IDE에서 VCL 폼 애플리케이션을 만드세요. 폼에 메모 두 개와 버튼 하나를 올려놓으면 전체 UI가 완성돼요.

폼 레이아웃

  • memoXMLTMemo, 서명되지 않은 XML을 여기에 붙여넣으세요.
  • memoSignedTMemo, 버튼 클릭 후 서명된 XML이 여기에 표시돼요.
  • btnSignTButton, 2단계의 OnClick 핸들러에 연결되어 있어요.
  • 디자인 타임 컴포넌트가 필요 없어요 — 모든 것이 코드로 생성돼요.
Unit1.dfm
object Form1: TForm1
  Caption = 'sgcSign Quick Start'
  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

서명 코드 추가하기

PFX 공급자를 로드하고, VeriFactu 프로파일로 문서 서명자를 지정한 다음 SignXML을 호출하세요.

Delphi

  • TsgcPFXKeyProvider는 Windows CNG를 통해 .pfx를 가져와요 — 원래 CSP에 관계없이 최신 SHA-256 서명이 작동해요.
  • TsgcDocumentSigner가 프로파일에 따라 올바른 XAdES 수준을 선택해요.
  • spVeriFactu는 스페인 AEAT VeriFactu를 선택해요 — XAdES-EPES, B-B, RSA-SHA256, 전용 C14N.
  • 21개 국가 프로파일 중 하나로 상수를 교체하세요 — 국가 프로파일을 참고하세요.
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

  • 동일한 구조, 동일한 클래스, 동일한 속성 이름 — C++ 래퍼는 Delphi API의 1:1 포트예요.
  • __finally 블록은 서명 중 예외가 발생해도 공급자가 해제되도록 보장해요.
  • UnicodeString이 종단 간에 사용되어요 — ANSI/UTF-8 변환을 걱정할 필요 없어요.
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;
  }
}

필요한 유닛 추가하기

uses 절에 두 개의 유닛 — PFX 공급자와 문서 서명자가 필요해요.

Delphi uses

각 키 공급자는 자체 유닛에 있으므로 참조하는 것에 대해서만 비용을 지불해요. sgcSign_DocumentSigner는 입력에 따라 XAdES, PAdES, 또는 CAdES를 선택하는 라우팅 레이어를 가져와요.

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

C++ Builder 인클루드

동일한 유닛이 .hpp 헤더로 노출돼요. C++ Builder 링커가 기본 정적 라이브러리를 자동으로 해석해요.

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

실행 및 테스트

F9를 눌러 실행하고, 위쪽 메모에 인보이스를 붙여넣은 다음 Sign XML을 클릭하세요. 서명된 봉투가 아래쪽 메모에 표시돼요.

컴파일 및 실행

IDE에서 F9를 눌러요. 폼이 메모 두 개와 버튼 하나와 함께 열려요. 예외도 없고 누락된 유닛도 없어요.

입력 붙여넣기

인보이스 XML(또는 올바른 형식의 XML)을 memoXML에 붙여넣어요. 서명자가 내부적으로 UTF-8로 정규화해요.

결과 확인

memoSigned에 이제 봉투된 <ds:Signature> 요소가 추가된 XML이 포함되어 있어요. 저장하고 XAdES 검증기를 통해 실행하거나 — TsgcSignatureVerifier를 직접 사용하세요.

유니코드와 WideString 오버로드

Delphi 7에서 stringAnsiString이에요. 폴란드어, 키릴 문자, 그리스 문자를 손실 없이 왕복 처리하려면 WideString 오버로드를 사용하세요.

주의 사항

Delphi 7에서 string 오버로드는 시스템 ACP를 통해 라우팅돼요. 'Jarosław'의 발음 구별 부호는 시스템 ACP가 CP1250일 때만 왕복 처리돼요. ACP가 CP1252이면 서명된 XML에서 문자가 손상돼요.

WideString 오버로드는 ACP를 완전히 우회해요 — CP_UTF8을 사용하여 WideCharToMultiByte로 UTF-16에서 UTF-8로 변환해요. Delphi 2009 이상에서는 두 오버로드가 동일해요. UnicodeString은 이미 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

모든 X.509 / CRL / OCSP / TSA 타임스탬프는 기본 ASN.1 사양에 맞춰 UTC TDateTime 값으로 저장돼요.

현지 시간으로 표시하기

최종 사용자 표시를 위해 각 컴포넌트의 *Local 속성(예: vCert.NotAfterLocal)을 사용하거나 유닛 sgcSign_TimesgcUTCToLocal로 수동으로 변환하세요.

이는 모두 UTC를 지정하는 RFC 5280(X.509), RFC 3161(TSA), RFC 6960(OCSP)과 일치해요. sgcUTCNow 헬퍼는 타임스탬프를 비교해야 하는 코드를 위해 현재 UTC TDateTime을 반환해요.

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);

다음으로 갈 곳

XAdES는 시작에 불과해요. PAdES, CAdES, 프로파일, 키 공급자, 중앙화된 서버 모두 클릭 한 번이면 돼요.

기능 개요

전체 XAdES, PAdES, CAdES API 인터페이스와 지원하는 타임스탬프 + OCSP 인프라를 둘러보세요.

더 보기 →

21개 국가 프로파일

VeriFactu, FatturaPA, KSeF, FACTUR-X 및 9개의 EU 고용 계약 프로파일이 있어요. 한 줄로 관할 구역을 전환할 수 있어요.

Read more →

10개 키 공급자

PFX, PEM, Windows 저장소, PKCS#11, Azure Trusted Signing, AWS KMS, Google KMS, Vault, Certum, CSC v2.

Read more →

sgcSign 서버

빌드 팜 전반에 걸쳐 서명을 중앙화해요. REST API, 웹 관리자, GitHub Actions, Azure DevOps, Jenkins, Docker를 지원해요.

Read more →

프로덕션 준비가 되셨나요?

체험판을 다운로드하고, 오늘 서명된 바이너리를 배포하고, 만족하시면 sgcSign을 라이선스 구매하세요.