최초 출시 후 단 한 달 만에 sgcSign 2026.5는 라이브러리의 대규모 확장을 제공합니다. 이번 릴리스는 Windows 바이너리용 Microsoft Authenticode 서명, 세 가지 새로운 코드 배포 서명자(ClickOnce, NuGet, VSIX), 완전한 EU eIDAS 준수 팩(ASiC 컨테이너, LOTL / EUTL 신뢰 목록, Cloud Signature Consortium 원격 서명), 9개의 사전 조정된 국가별 고용 프로파일, 불가리아 Peppol BIS Billing 3.0 프로파일, 네이티브 QR 코드 생성기, ECDSA P-256/384/521 및 RSA-PSS 지원, 전체 CI/CD 통합, 그리고 광범위한 XAdES / PFX 적합성 수정 사항을 추가합니다.
이 게시물은 주요 사항을 살펴보며, 모든 새 컴포넌트에 대해 바로 붙여넣을 수 있는 Delphi 스니펫을 제공합니다.
Microsoft Authenticode
TsgcAuthenticodeSigner는 Authenticode 사양에 따라 Windows 휴대용 실행 파일(.exe, .dll, .sys)에 서명합니다. 서명자는 PE를 파싱하고 Authenticode 알고리즘으로 해시를 계산하며(체크섬과 기존 인증서 테이블은 건너뜀), SPC 간접 데이터 콘텐츠가 포함된 전체 PKCS#7 SignedData blob을 만든 다음 이를 바이너리의 인증서 테이블에 추가합니다.
SHA-1부터 SHA-512까지의 해시가 지원되고, RFC 3161 타임스탬프는 서명되지 않은 속성으로 포함되며, AppendSignature := True는 중첩 서명(예: 레거시 Windows 호환성을 위한 SHA-1 + SHA-256 이중 서명)을 생성합니다.
uses
sgcSign_Authenticode, sgcSign_KeyProvider_PFX, sgcSign_TSAClient;
var
oSigner: TsgcAuthenticodeSigner;
oPFX: TsgcPFXKeyProvider;
oTSA: TsgcTSAClient;
begin
oPFX := TsgcPFXKeyProvider.Create(nil);
oPFX.FileName := 'codesign.pfx';
oPFX.Password := 'secret';
oTSA := TsgcTSAClient.Create(nil);
oTSA.URL := 'http://timestamp.digicert.com';
oSigner := TsgcAuthenticodeSigner.Create(nil);
try
oSigner.KeyProvider := oPFX;
oSigner.TSAClient := oTSA;
oSigner.Hash := ahSHA256; // ahSHA1 / ahSHA256 / ahSHA384 / ahSHA512
oSigner.Level := alT; // alBES or alT (with timestamp)
oSigner.Description := 'My Application';
oSigner.URL := 'https://www.example.com';
oSigner.SignFile('MyApp.exe', 'MyApp-signed.exe');
finally
oSigner.Free; oTSA.Free; oPFX.Free;
end;
end;
검증은 대칭적입니다. TsgcAuthenticodeVerifier.Verify는 결과, 계산된 해시와 포함된 해시, 서명자 주체/발급자, 그리고 타임스탬프 존재 여부를 포함하는 레코드를 반환합니다.
var
oVer: TsgcAuthenticodeVerifier;
oRes: TsgcAuthenticodeVerifyResult;
begin
oVer := TsgcAuthenticodeVerifier.Create(nil);
try
oRes := oVer.Verify('MyApp-signed.exe');
if oRes.Valid then
ShowMessage('Signed by ' + oRes.SubjectName)
else
ShowMessage('Invalid: ' + oRes.ErrorMessage);
finally
oVer.Free;
end;
end;
해시 전용 Authenticode 서명
대용량 CI 아티팩트(설치 프로그램, 런타임, 드라이버)는 전체 PE를 원격 서명자에 업로드하는 것이 부담스럽습니다. 새로운 해시 전용 서명 흐름을 사용하면 클라이언트가 로컬에서 Authenticode 해시를 계산하고 32바이트 다이제스트만 sgcSign Server로 전송할 수 있습니다. 서버는 분리된 PKCS#7 blob을 반환하고 클라이언트는 이를 다시 바이너리에 포함시킵니다. 이를 통해 대역폭이 제한된 에이전트에서 메가바이트 단위의 업로드를 몇 KB로 줄일 수 있습니다.
// Local: compute the hash with sgcSign_PE_Hasher, POST it to the server,
// receive the SignedData blob, then append it to the PE's certificate table.
var
oSigner: TsgcAuthenticodeSigner;
vHash, vPKCS7: TBytes;
begin
// vHash := ComputePEHash('MyApp.exe', haSHA256);
vPKCS7 := oSigner.SignHash(vHash, ahSHA256);
// EmbedPKCS7IntoPE('MyApp.exe', vPKCS7, 'MyApp-signed.exe');
end;
동일한 작업이 서버의 POST /api/v1/sign/authenticode/hash 엔드포인트, sgcsign sign --prehash CLI 플래그, 그리고 .NET SDK의 TsgcSignClient.SignAuthenticodeHashAsync 메서드를 통해 노출됩니다.
ClickOnce, NuGet 및 VSIX 서명자
세 가지 새로운 서명자가 Microsoft 개발자 배포 생태계를 다룹니다.
TsgcClickOnceSigner는 enveloped W3C XML-DSig를 사용하여 .application 배포 매니페스트와 .exe.manifest 애플리케이션 매니페스트에 서명하며, Microsoft mage.exe의 출력과 일치합니다. 서명자는 인증서의 issuerKeyHash로 publisherIdentity 노드를 다시 작성합니다.
uses sgcSign_ClickOnce;
var oCO: TsgcClickOnceSigner;
begin
oCO := TsgcClickOnceSigner.Create(nil);
try
oCO.KeyProvider := oPFX;
oCO.Hash := haSHA256;
oCO.PublisherName := 'My Company';
oCO.SignManifestFile('MyApp.application', 'MyApp-signed.application');
finally
oCO.Free;
end;
end;
TsgcNuGetSigner는 .nupkg 작성자 패키지에 서명하여 CMS/PKCS#7 SignedData blob(서명 인증서 v2, 커밋 유형 "proof of origin")을 생성하며 선택적인 RFC 3161 카운터서명을 포함합니다.
uses sgcSign_NuGet;
var oNu: TsgcNuGetSigner;
begin
oNu := TsgcNuGetSigner.Create(nil);
try
oNu.KeyProvider := oPFX;
oNu.TSAClient := oTSA;
oNu.Hash := haSHA256;
oNu.SignPackageFile('MyLib.1.0.0.nupkg', 'MyLib.1.0.0.signed.nupkg');
finally
oNu.Free;
end;
end;
TsgcVSIXSigner는 Visual Studio 확장에 대한 OPC(Open Packaging Convention) 디지털 서명을 구현하며, 파트별 XML-DSig 참조를 계산하고 [Content_Types].xml과 패키지 _rels/.rels를 다시 작성합니다.
uses sgcSign_VSIX;
var oVX: TsgcVSIXSigner;
begin
oVX := TsgcVSIXSigner.Create(nil);
try
oVX.KeyProvider := oPFX;
oVX.Hash := haSHA256;
oVX.SignPackageFile('MyExt.vsix', 'MyExt-signed.vsix');
finally
oVX.Free;
end;
end;
세 가지 모두 기존 XAdES / PAdES / CAdES 서명자와 동일한 IsgcKeyProvider 인터페이스를 재사용하므로, 송장 서명용으로 구성된 AWS KMS, Azure Trusted Signing 또는 PKCS#11 토큰을 추가 작업 없이 바이너리 서명에 재사용할 수 있습니다.
EU eIDAS / 준수 팩
이번 릴리스는 eIDAS 팩을 도입합니다. 이 세 가지 새 유닛이 함께 Delphi 애플리케이션이 공식 EU 신뢰 프레임워크에 대해 서명을 검증하고 장기 보관용 컨테이너를 생성할 수 있게 합니다.
ASiC 컨테이너 (ETSI EN 319 162-1)
sgcSign_ASiC는 XAdES와 CAdES 형식 모두에서 ASiC-S(단일 문서) 및 ASiC-E(다중 문서) 컨테이너를 빌드하고 파싱합니다. 출력은 mimetype 항목이 먼저 오고 서명이 META-INF/ 아래에 배치된 결정적 ZIP입니다.
uses sgcSign_ASiC;
var
oDocs: TsgcASiCDocumentArray;
vBytes: TBytes;
begin
SetLength(oDocs, 1);
oDocs[0].Name := 'invoice.xml';
oDocs[0].Data := TFile.ReadAllBytes('invoice.xml');
// aSignatureXML comes from TsgcXAdESSigner (detached signature over the doc)
vBytes := TsgcASiCContainer.BuildXAdES(apASiCE, oDocs, vXAdESSignature);
TFile.WriteAllBytes('invoice.asice', vBytes);
end;
LOTL / EUTL 신뢰 목록
sgcSign_TrustList는 EU의 List of Trusted Lists를 다운로드하고, 회원국별 신뢰 목록 포인터를 따라가며, 각 TSPService 항목을 파싱합니다. 결과는 31개 회원국에 걸친 약 3,600개 서비스의 인메모리 카탈로그입니다. IsQualifiedAtTime 조회는 주어진 서명 시점에 모든 인증서를 "공인 TSP가 발급한"으로 분류합니다. 이는 eIDAS 25조에 따라 서명을 고급(AdES)에서 적격(QES)으로 업그레이드하는 데 필요한 작업입니다.
Cloud Signature Consortium (CSC v2)
TsgcCSCKeyProvider는 Cloud Signature Consortium API v2용 IsgcKeyProvider 구현입니다. 이는 Buypass, Certinomis, Globalsign EU, InfoCert, Namirial, Trust Pro 및 기타 QTSP가 사용하는 원격 적격 서명을 위한 유럽 표준입니다. 제공자는 Basic / OAuth2 / OTP 인증을 처리하고, 사용자의 자격 증명을 나열하며, 인증서 체인을 가져오고, SAD 인증을 사용하여 해시 전용 원격 서명을 수행합니다.
uses sgcSign_KeyProvider_CSC, sgcSign_XAdES;
var oCSC: TsgcCSCKeyProvider; oX: TsgcXAdESSigner;
begin
oCSC := TsgcCSCKeyProvider.Create(nil);
oCSC.BaseURL := 'https://csc.example-qtsp.eu/csc/v2';
oCSC.AuthMethod := cscOAuth2;
oCSC.OAuthClientID := 'my-client-id';
oCSC.OAuthClientSecret := 'my-client-secret';
oCSC.CredentialID := oCSC.ListCredentials[0];
oCSC.PIN := '1234';
oCSC.OTP := '987654'; // pushed via SMS / app
oCSC.LoadCredentialInfo;
oX := TsgcXAdESSigner.Create(nil);
oX.KeyProvider := oCSC;
oX.Profile := spEIDAS;
oX.SignXML(vXML);
end;
9개의 고용 프로파일
9개의 사전 조정된 프로파일은 유럽 노동법 문서(고용 계약, 급여 명세서, 이전 계약)를 대상으로 합니다:
| 프로파일 | 국가 | 레벨 | C14N | TSA | OCSP |
|---|---|---|---|---|---|
spEmploymentDE | 독일 | B-LT | Exclusive | 예 | 예 |
spEmploymentIT | 이탈리아 | B-LT | C14N 1.0 | 예 | 예 |
spEmploymentES | 스페인 | B-T | Exclusive | 예 | 아니오 |
spEmploymentFR | 프랑스 | B-T | Exclusive | 예 | 아니오 |
spEmploymentPL | 폴란드 | B-T | Exclusive | 예 | 아니오 |
spEmploymentAT | 오스트리아 | B-LT | Exclusive | 예 | 예 |
spEmploymentBE | 벨기에 | B-LT | Exclusive | 예 | 예 |
spEmploymentPT | 포르투갈 | B-LT | Exclusive | 예 | 예 |
spEmploymentNL | 네덜란드 | B-T | Exclusive | 예 | 아니오 |
새로운 EU_Employment 데모는 전체 파이프라인(서명 → ASiC-E 패키지 → LOTL 검증 → QTSP 분류)을 제공합니다.
불가리아 Peppol BIS Billing 3.0
새로운 TsgcProfilePeppolBG 프로파일은 불가리아 UBL 2.1 송장(BGN 통화, 20% 부가가치세, BG VAT / EIK, BG IBAN, 스키마 ID 9926 엔드포인트)에 exclusive C14N을 사용하여 XAdES B-T로 서명합니다. Delphi 및 C++Builder 데모는 완전히 채워진 송장 템플릿을 제공합니다.
uses sgcSign_XAdES, sgcSign_Types;
var oSigner: TsgcXAdESSigner;
begin
oSigner := TsgcXAdESSigner.Create(nil);
try
oSigner.KeyProvider := oPFX;
oSigner.TSAClient := oTSA;
oSigner.Profile := spPeppolBG;
oSigner.SignXMLFile('invoice_bg.xml', 'invoice_bg_signed.xml');
finally
oSigner.Free;
end;
end;
CI/CD 통합
sgcSign Server는 이제 모든 일반적인 파이프라인에 대해 일급 아티팩트를 제공합니다:
- GitHub Actions — 해시 전용 Authenticode 서명이 포함된 복합 Action.
- Azure DevOps — 보안 파일 통합이 포함된 네이티브 작업.
- Jenkins — 선언적 파이프라인 DSL과 공유 라이브러리.
- Docker — Windows Server Core 이미지와
docker-compose파일. - Helm — 고가용성 sgcSign Server를 위한 Kubernetes 차트.
QR 코드 생성기
인쇄 가능한 송장에 QR 코드가 필요한 TicketBAI, VeriFactu 및 유사한 프로파일을 위해, 새로운 sgcSign_QRCode 유닛은 ISO/IEC 18004를 바이트 모드로 구현하는 순수 Pascal 생성기를 제공합니다. 네 가지 ECC 레벨 모두, 버전 1부터 40까지, GF(256) Reed-Solomon, 전체 마스크 패널티 점수 계산을 TBitmap 렌더러와 함께 제공합니다. 외부 DLL이 없으며 라이선스 문제도 없습니다.
uses sgcSign_QRCode, Graphics;
var
oMatrix: TQRMatrix;
oBmp: TBitmap;
begin
oMatrix := GenerateQRCode(
'https://tbai.eus/QURL/123456789-A?cr=42',
qrECM);
oBmp := TBitmap.Create;
try
RenderQRMatrix(oMatrix, oBmp, 5, 4); // 5 px / module, 4-module border
oBmp.SaveToFile('invoice_qr.bmp');
finally
oBmp.Free;
end;
end;
ECDSA P-256 / P-384 / P-521 및 RSA-PSS
TsgcPEMKeyProvider는 이제 Windows BCrypt CNG(ECCPRIVATEBLOB)를 통해 EC 개인 키를 가져오고 XML-DSig용 원시 r||s 출력으로 서명합니다. 새로운 SignDataPSS 메서드는 BCRYPT_PAD_PSS를 사용하여 RSA-PSS 서명(SHA-256, salt = 32바이트)을 생성합니다. 이는 점점 더 많은 국가별 e-인보이싱 프로파일에서 요구되고 있습니다.
검증 측면에서는 TsgcSignatureVerifier가 BCRYPT_ECCPUBLIC_BLOB에서 EC 공개 키를 가져와 XAdES SignatureValue와 원시 VerifyData 코드 경로 모두에서 동일한 세 곡선에 대한 ECDSA 서명을 검증합니다.
이를 작동시키기 위해 TsgcX509Certificate는 이제 KeyUsage 확장을 파싱하고 KeyUsage 속성과 HasKeyUsageDigitalSignature / HasKeyUsageNonRepudiation 도우미를 통해 이를 노출합니다. 또한 새로운 PublicKeyParameters 속성은 원시 AlgorithmIdentifier 매개변수 TLV(EC 인증서의 명명된 곡선 OID)를 노출합니다.
Delphi 7용 WideString 오버로드
비 ACP 텍스트(폴란드 KSeF, 그리스 myDATA, 불가리아 Peppol 등)를 전달하는 호출자를 위해, 공개 서명 및 검증 API는 이제 TsgcXAdESSigner.SignXML, SignXMLDetached, SignXMLEnveloping(및 TsgcDocumentSigner와 TsgcSignatureVerifier의 일치하는 메서드)에 WideString 오버로드를 노출합니다. 이는 Delphi 7에서 ACP 라운드트립 없이 무손실 유니코드 입출력을 보장하며, Delphi 2009+에서 string 오버로드와 동등합니다.
적합성 및 안정성 수정
2026.5의 버그 수정 일괄 처리는 실제 세무 당국 엔드포인트에 대해 발견된 XAdES / PFX / 검증자 문제의 긴 목록을 해결합니다.
TsgcDocumentSigner는 이제 AdES 프로파일에 대해 XAdES를 올바르게 생성합니다. 내부적으로sfXAdES경로에 대해TsgcXAdESSigner에 위임하고,sfPAdES/sfCAdES에 대해서는 명확한 오류를 발생시킵니다(전용 서명자 사용). 새로운 publishedFormat: TsgcSignatureFormat속성(기본값sfXAdES)이 선택을 명시적으로 만듭니다. 이전 버전은 프로파일에 관계없이 일반 XML-DSig를 내보냈는데, 이는 국가별 e-인보이싱 서비스에서 거부되었습니다.TsgcPFXKeyProvider는 새로운 publishedHashAlgorithm속성(기본값haSHA256)을 얻었으며,TsgcXAdESSigner는 이제 활성 프로파일의 해시를 PFX 제공자에 전달합니다. FacturaeB2B 서명 PFX 기반 송장은 이제 올바르게 RSA-SHA1이 되어 FACe INVALID_INVOICE-122 «los datos de la firma no son correctos» 거부를 수정합니다.TsgcPFXKeyProvider는 이제 최신 P12 파일을 지원합니다:PKCS12_PREFER_CNG_KSP, 다중 인증서 반복 및 탐색, 2단계 획득(ONLY_NCRYPT후PREFER_NCRYPT) 및NCryptSignHash를 통한 CNG 서명.- XAdES KSeF / ETSI 적합성 — V1
SigningCertificate래퍼, 조건부SignaturePolicyIdentifier발행, 십진수X509SerialNumber, 단일 빌드SignedProperties(클럭 경쟁 수정),SignedProperties참조에 명시적인 exc-c14n 변환, 그리고 새로운SignatureParentElement속성.TsgcSignatureVerifier는 이제 요소 ID 조회를 통해URI=#<Id>를 해석합니다. - X.509 확장 파싱 — v3
[3] EXPLICIT Extensions태그 콘텐츠가 이중 래핑되어 모든 인증서에서KeyUsage,ExtendedKeyUsage, AIA, CDP, SubjectAltName 및 BasicConstraints가 자동으로 건너뛰어졌습니다. 수정됨. - 자체 종료 XML 태그 —
ExtractFullElement는 이제<ds:DigestMethod Algorithm="…/sha1"/>를 올바르게 처리합니다. 이전 버전은 기본적으로 SHA-256으로 설정되어 "Digest length mismatch for Reference 0"로 FacturaeB2B 검증을 손상시켰습니다. - Inclusive C14N 폴백 —
TsgcSignatureVerifier는 XML-DSig §4.3.3.2에 따라 명시적 변환을 생략하는 fragment / empty-URI 참조에 암시적 inclusive C14N을 적용합니다. inclusive-C14N 프로파일(FacturaeB2B)에서 KeyInfo 및 본문 참조에 대한 "Digest value mismatch"를 수정합니다. - PEM 강화 — 유니코드
ReadFileContent수정, 2단계 PKCS#8 디코딩,AT_KEYEXCHANGEkeyspec, GUID 접미사 CSP 컨테이너, BCrypt를 통한 네이티브 암호화 PKCS#8(PBES2 / PBKDF2 / AES-CBC),LoadCertificateOnly및 EC 마커 인식. - 디자인 타임 정리 — 9개의 모든 서명자 / 검증자 컴포넌트는 이제
Notification(opRemove)를 통해 연결된 참조를 자동으로 지워, 키 제공자나 TSA 클라이언트가 폼에서 삭제될 때 댕글링 포인터를 제거합니다. - 빌드 위생 —
sgcSign_ASiC의 W1000(UTF8Decode)이{$IFDEF UNICODE} UTF8ToString폴백을 통해 수정되었으며,sgcSign_XAdES와sgcSign_TrustList의 H2077 / H2219 데드 코드 경고가 정리되었습니다.
업그레이드
2026.5는 기존 2026.4 프로젝트에 대한 드롭인 업그레이드입니다. 주의해야 할 단일 동작 변경 사항은 TsgcDocumentSigner입니다: AdES 프로파일에 대해 일반 XML-DSig를 내보내는 데 의존했던 코드는 이제 올바르게 XAdES를 생성합니다. 이는 세무 당국이 요청한 것이지만, 통합 테스트가 레거시 출력에 고정되어 있었다면 골든 파일을 새로 고쳐야 합니다.
활성 구독을 보유한 고객은 고객 영역에서 새 빌드를 다운로드할 수 있습니다. 평가판 사용자는 esegece.com/products/sgcsign/sgcsign-download에서 업데이트된 설치 프로그램을 받을 수 있습니다.
질문, 피드백 또는 마이그레이션 도움이 필요하신가요? 문의하기 — 코드를 작성한 사람들로부터 직접 답변을 받으실 수 있습니다.
