最初の文書に 5 分で署名する

新規 VCL プロジェクトから署名済み XAdES エンベロープまでの完全なウォークスルーです。Delphi 7 ~ RAD Studio 13 および C++Builder に対応しています。

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

始める前に

必要なのは 2 つだけです。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 フォームアプリケーションを作成します。フォームに 2 つのメモと 1 つのボタンを配置します。これがすべての 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、exclusive 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 句に 2 つのユニットを追加します。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 を押します。2 つのメモとボタンを持つフォームが開きます。例外なし、欠落ユニットなしです。

入力を貼り付ける

任意の請求書 XML(またはすべての整形式 XML)を memoXML にドロップします。サイナーは内部で UTF-8 に正規化します。

結果を確認する

memoSigned にはエンベロープされた <ds:Signature> 要素が追加された XML が含まれています。保存して任意の XAdES 検証ツールで検証するか、TsgcSignatureVerifier を直接使用してください。

Unicode と 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 で手動変換します。

これは RFC 5280(X.509)、RFC 3161(TSA)、RFC 6960(OCSP)に準拠しており、いずれも UTC を指定しています。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、プロファイル、キープロバイダー、中央集権サーバーはすべて 1 クリックで利用できます。

機能の概要

完全な XAdES、PAdES、CAdES API サーフェスとサポートするタイムスタンプ + OCSP インフラストラクチャーを確認できます。

続きを読む →

21 の国別プロファイル

VeriFactu、FatturaPA、KSeF、FACTUR-X、および EU の雇用契約プロファイル 9 件。1 行で管轄を切り替えられます。

続きを読む →

10 のキープロバイダー

PFX、PEM、Windows ストア、PKCS#11、Azure Trusted Signing、AWS KMS、Google KMS、Vault、Certum、CSC v2 に対応しています。

続きを読む →

sgcSign サーバー

ビルドファーム全体で署名を一元管理します。REST API、Web 管理画面、GitHub Actions、Azure DevOps、Jenkins、Docker に対応しています。

続きを読む →

本番環境の準備はできましたか?

トライアルをダウンロードして今日から署名済みバイナリを出荷し、満足したら sgcSign をライセンスしてください。