sgcSign 2026.5 — Authenticode、欧盟 eIDAS 套件与 9 个雇佣配置文件

· 版本发布

距首次发布仅一个月,sgcSign 2026.5 带来了对该库的一次重大扩展。本次发布新增了面向 Windows 二进制文件的 Microsoft Authenticode 签名、三款新的代码分发签名器(ClickOnce、NuGet、VSIX)、完整的欧盟 eIDAS 合规套件(ASiC 容器、LOTL / EUTL 信任列表、云签名联盟远程签名)、九个预调优的国家雇佣配置文件、一个保加利亚 Peppol BIS Billing 3.0 配置文件、一个原生 QR Code 生成器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 数据块,并将其追加到二进制文件的证书表中。

支持从 SHA-1 到 SHA-512 的哈希算法,RFC 3161 时间戳作为未签名属性嵌入,而 AppendSignature := True 会生成嵌套签名(例如 SHA-1 + SHA-256 双重签名以保证旧版 Windows 的兼容性)。

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 数据块,客户端再将其嵌回到二进制文件中 — 在带宽受限的代理上将数兆字节的上传量缩减到几 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 使用封套式 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 数据块(带签名证书 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(开放打包约定)数字签名,计算每个 part 的 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 令牌可以直接复用于二进制签名,无需额外的管道工作。

欧盟 eIDAS / 合规套件

本次发布引入了 eIDAS 套件 — 三个新单元,让 Delphi 应用能够根据官方欧盟信任框架验证签名,并生成长期归档容器。

ASiC 容器(ETSI EN 319 162-1)

sgcSign_ASiC 以 XAdES 和 CAdES 两种风格构建和解析 ASiC-S(单文档)与 ASiC-E(多文档)容器。输出是一个确定性的 ZIP,其中 mimetype 条目位于最前,签名放置在 META-INF/ 下。

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 下载欧盟可信列表清单(List of Trusted Lists),跟随每个成员国的信任列表指针,并解析每个 TSPService 条目。其结果是一个内存中的目录,包含 31 个成员国大约 3,600 项服务。IsQualifiedAtTime 查找方法可在给定的签名时间将任何证书归类为"由合格 TSP 颁发" — 这是根据 eIDAS 第 25 条将签名从高级(AdES)升级到合格(QES)所需的操作。

云签名联盟(CSC v2)

TsgcCSCKeyProvider 是一个针对云签名联盟 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;

九个雇佣配置文件

九个预调优的配置文件针对欧洲劳动法文档(雇佣合同、工资单、转岗协议):

配置文件国家等级C14NTSAOCSP
spEmploymentDE德国B-LTExclusive
spEmploymentIT意大利B-LTC14N 1.0
spEmploymentES西班牙B-TExclusive
spEmploymentFR法国B-TExclusive
spEmploymentPL波兰B-TExclusive
spEmploymentAT奥地利B-LTExclusive
spEmploymentBE比利时B-LTExclusive
spEmploymentPT葡萄牙B-LTExclusive
spEmploymentNL荷兰B-TExclusive

新的 EU_Employment 演示提供了完整的流水线(签名 → ASiC-E 打包 → LOTL 验证 → QTSP 分类)。

保加利亚 Peppol BIS Billing 3.0

新的 TsgcProfilePeppolBG 配置文件在 XAdES B-T 等级下以独占 C14N 对保加利亚 UBL 2.1 发票(BGN 货币、20% 增值税、BG VAT / EIK、BG IBAN、scheme ID 9926 端点)进行签名。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 现在为每种常见的流水线提供一流的工件:

QR Code 生成器

对于 TicketBAI、VeriFactu 等需要在可打印发票上加入二维码的配置文件,新的 sgcSign_QRCode 单元提供了一个纯 Pascal 生成器,以字节模式实现 ISO/IEC 18004 — 涵盖全部四个 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,盐值 = 32 字节) — 越来越多的国家电子发票配置文件需要这种签名。

在验证端,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.SignXMLSignXMLDetachedSignXMLEnveloping(以及 TsgcDocumentSignerTsgcSignatureVerifier 上的相应方法)上提供了 WideString 重载。这保证了在 Delphi 7 上 Unicode 输入/输出的无损 — 无 ACP 往返 — 等同于 Delphi 2009+ 上的 string 重载。

合规性与可靠性修复

2026.5 的错误修复批次关闭了一长串针对实际税务机关端点发现的 XAdES / PFX / 验证器问题。

升级

对于现有的 2026.4 项目,2026.5 是即插即用的升级。需要注意的唯一行为变化是 TsgcDocumentSigner:依赖它为 AdES 配置文件发出纯 XML-DSig 的代码现在将正确生成 XAdES — 这正是税务机关所要求的,但如果您的集成测试固定到了旧的输出,则需要刷新黄金文件。

拥有有效订阅的客户可以从客户区域下载新版本。试用用户可以在 esegece.com/products/sgcsign/sgcsign-download 获取更新的安装程序。

有问题、反馈或迁移帮助?联系我们 — 您会收到编写代码的人的回复。