TPDFlibPKCS11Client

セキュリティと署名

説明

ベンダーのPKCS #11モジュールを実行時に読み込み、Windows CSPやKSPプロバイダーに登録されていない証明書と秘密鍵を公開します

クライアントは存在するトークンを列挙し、永続セッションを開き、ユーザーを認証し、バイナリのCKA_IDでX.509証明書と署名鍵をペアにし、計算済みのダイジェストをCKM_RSA_PKCSまたはCKM_ECDSAで署名します

明示的な証明書省略可能の探索は、ラベルまたはバイナリIDでML-DSA秘密鍵を選択し、そのCKA_PARAMETER_SETを検証し、元のメッセージをCKM_ML_DSAで署名できます

SignDigestはTPDFlibExternalDigestSignEventを実装し、TPDFlib.OnExternalDigestSignへ直接代入できます

ユニット

PDFlibPKCS11

生成とモジュールのライフサイクル

Constructor TPDFlibPKCS11Client.Create;
Destructor TPDFlibPKCS11Client.Destroy;
Function TPDFlibPKCS11Client.LoadModule: Boolean;
Procedure TPDFlibPKCS11Client.UnloadModule;
Function TPDFlibPKCS11Client.UseFunctionList(FunctionList: PPLPKCS11FunctionList; AlreadyInitialized: Boolean): Boolean;

ModulePathは、C_GetFunctionListをエクスポートするWin32またはWin64のPKCS #11 DLLを識別します

同じパスを使うクライアントは、読み込み済みモジュールと均衡の取れたC_Initialize/C_Finalizeの生存期間を1つ共有します

ローダーは最初にCKF_OS_LOCKING_OKを要求します。内部ロックを提供できないモジュールは共有呼び出しロックで保護され、準拠モジュールでは別々のクライアントセッションが並行して動作できます

UseFunctionListは静的リンク、組み込み、アプリケーション管理のプロバイダーをサポートします。呼び出し元は、UnloadModuleまたは破棄まで供給されたテーブルを生存させておく必要があります

トークンの検出と接続

Function TPDFlibPKCS11Client.RefreshTokens: Boolean;
Function TPDFlibPKCS11Client.GetToken(Index: Integer; Out Token: TPDFlibPKCS11Token): Boolean;
Function TPDFlibPKCS11Client.Connect: Boolean;
Procedure TPDFlibPKCS11Client.Disconnect;
Function TPDFlibPKCS11Client.GetSelectedToken(Out Token: TPDFlibPKCS11Token): Boolean;
Property TPDFlibPKCS11Client.TokenCount: Integer;

RefreshTokens はホットプラグイベントが数値を変えた場合に、制限付きの再試行で存在するスロットを列挙し、TokenCount は最後の更新が見つけたトークンの数を報告します

SlotID、TokenLabel、TokenSerial、またはその組み合わせでトークンを選択します。空の選択は、存在するトークンがちょうど 1 つの場合にのみ成功します

TPDFlibPKCS11Token はスロットの説明、製造元、トークンラベル、モデル、シリアル番号、フラグ、PIN 長の範囲を報告します

アイデンティティの選択

CertificateLabelX.509証明書オブジェクトのオプションのUTF-8 CKA_LABELフィルターです
CertificateIDAnsiStringに保存されるオプションのバイナリCKA_IDフィルターです
PrivateKeyLabel秘密署名鍵のオプションのUTF-8 CKA_LABELフィルターです
PrivateKeyIDオプションのバイナリ秘密鍵CKA_IDです。空の場合は証明書のIDが再利用されます
CertificateOptional既定はFalseです。Trueの場合は秘密鍵のラベルまたはIDが必要となり、探索はX.509証明書を持たないML-DSA鍵だけを受け入れます

既定の探索は曖昧さのない証明書と鍵の1組を要求し、CKA_SIGN=Trueを要求し、証明書DERを検証し、RSA/ECの型不一致を拒否します。証明書省略可能の探索は曖昧さのないML-DSA鍵を要求し、パラメーターセット44、65、87を検証します

解決されたML-DSAパラメーターセットはMLDSAParameterSetで公開されます

解決された証明書はCertificateDERで、選択された鍵IDはResolvedPrivateKeyIDで公開されます

認証

UserPINUTF-8 でエンコードされた書き込み専用のユーザー PIN。トークンの範囲に対して検査され、置き換えや破棄の際に消去されます
UseProtectedAuthenticationPathトークンが CKF_PROTECTED_AUTHENTICATION_PATH を広告する場合に null PIN を渡します
ReadWriteSessionCKF_RW_SESSION を追加します。署名には通常、既定の読み取り専用シリアルセッションだけで十分です

CKA_ALWAYS_AUTHENTICATE=True の鍵は、成功した C_SignInit のたびにコンテキスト固有のログインを受け取ります

ClearPIN は構成された PIN を上書きして解放します

署名

Function TPDFlibPKCS11Client.SupportsMechanism(MechanismType: Cardinal): Boolean;
Function TPDFlibPKCS11Client.SupportsAlgorithm(DigestAlgorithm, SignatureAlgorithm: Integer): Boolean;
Function TPDFlibPKCS11Client.SignMLDSA(Const Message: AnsiString; Out Signature: AnsiString): Boolean;
Function TPDFlibPKCS11Client.SignHash(Const Digest: AnsiString; DigestAlgorithm, SignatureAlgorithm: Integer; Out Signature: AnsiString): Boolean;
Function TPDFlibPKCS11Client.SignDigest(Sender: TObject; SignProcessID: Integer; Const Digest: AnsiString; DigestAlgorithm, SignatureAlgorithm: Integer; Var Signature: AnsiString): Boolean;

RSA署名はローカルで構築されたDER DigestInfoを使う生のCKM_RSA_PKCSを使用するため、トークンがPDFダイジェストを2度ハッシュすることはありません

ECDSA署名は生のCKM_ECDSAを使います。トークンのP1363出力はPDF_EXTERNAL_SIGNATURE_ECDSA_P1363ではそのまま返され、PDF_EXTERNAL_SIGNATURE_ECDSA_DERでは厳密なDERへ変換されます

SignMLDSAは元のメッセージを、空のメカニズムパラメーターを持つシングルパートのCKM_ML_DSAへ渡し、既定の空コンテキストを選択します。SignHashやCMSダイジェストコールバックとは独立です

SHA-1、SHA-256、SHA-384、SHA-512、SHA3-256、SHA3-384、SHA3-512のダイジェスト長は、秘密鍵操作の前に検証されます

失われたセッションの再オープンと再試行は、署名開始前にC_SignInitが失敗した場合にだけ行われ、曖昧なC_Sign失敗後の秘密鍵操作の重複を避けます

例

var
  Token: TPDFlibPKCS11Client;
  ProcessID: Integer;
begin
  Token:= TPDFlibPKCS11Client.Create;
  try
    Token.ModulePath:= 'C:\Program Files\Vendor\pkcs11.dll';
    Token.TokenLabel:= 'Signing token';
    Token.CertificateLabel:= 'Document signer';
    Token.UserPIN:= UserPIN;
    if not Token.Connect then
      raise Exception.Create(String(Token.LastError));

    PDF.OnExternalDigestSign:= Token.SignDigest;
    ProcessID:= PDF.NewSignProcessFromFile(InputFile, '');
    PDF.SetSignProcessField(ProcessID, 'Approval');
    PDF.SetSignProcessDigestAlgorithm(ProcessID, 2);
    PDF.SetSignProcessExternalDigestSigner(ProcessID,
      Token.CertificateDER, PDF_EXTERNAL_SIGNATURE_RSA_PKCS1, 512);
    PDF.EndSignProcessToFile(ProcessID, OutputFile);
  finally
    Token.Free;
  end;
end;

状態と失敗時の動作

Connected、KeyType、MLDSAParameterSet、AlwaysAuthenticate、FunctionListMajor、FunctionListMinor はアクティブなプロバイダの状態を公開しますモジュールの読み込み、トークン選択、認証、オブジェクト検出、属性境界、機構の検査、署名のいずれかが失敗すると、メソッドは

False を返し LastReturnValue と LastError の両方を設定します

関連項目

OnExternalDigestSign, SetSignProcessExternalDigestSigner, SetSignProcessDigestAlgorithm, TPDFlibCSCClient

PIN管理

Function TPDFlibPKCS11Client.InitializeUserPIN(Const SecurityOfficerPIN, NewUserPIN: WideString): Boolean;
Function TPDFlibPKCS11Client.ChangeUserPIN(Const OldPIN, NewPIN: WideString): Boolean;

両操作は設定されたトークン上に独自の読み書きセッションを開き、署名セッションには触れません。InitializeUserPINはC_InitPINの呼び出し前にセキュリティオフィサーとしてログインし、ChangeUserPINはC_SetPINの呼び出し前にユーザーとしてログインします

PINバッファは使用後に消去されます。必要なエントリポイントを持たないモジュールは、黙って失敗する代わりにエラーを報告します