EPdfPkcs11Error = class(Exception);
TPdfPkcs11Options = record
ModulePath: string;
SlotId: UInt64;
UseSpecificSlot: Boolean;
Pin: string;
CertificateLabel: string;
class function Default: TPdfPkcs11Options; static;
end;
TPdfPkcs11SignerProvider = class(TInterfacedObject, IPadesSignerProvider,
IPdfPkcs11SignerProvider)
constructor Create(const Options: TPdfPkcs11Options);
destructor Destroy; override;
function BackendName: string;
function Resolve(const Options: TPadesSignerOptions): TPadesResolvedSigner;
function EnumerateSlots: TPdfPkcs11Slots;
function EnumerateCertificates(SlotID: UInt64): TPdfPkcs11Certificates;
procedure CloseProtectedSessions;
end;
function Pkcs11ModuleAvailable(const ModulePath: string): Boolean;
function Pkcs11ModuleVersion(const ModulePath: string): string;
function Pkcs11AbiLayout: string;
function ConfigurePkcs11SignerProvider(
const Options: TPdfPkcs11Options): IPdfPkcs11SignerProvider;
FPdfPkcs11 是可攜的 PAdES 簽署後端,對應 Windows 上的 CNG 後端。它從 PKCS#11 權杖解析簽署者憑證及其私鑰,然後傳回 TPadesResolvedSigner,其 ICmsSigner 透過權杖產生 SignerInfo 簽章,因此私鑰從不離開權杖
模組在執行期按路徑載入——opensc-pkcs11.so、libsofthsm2.so 或廠商 DLL——因此編譯時不連結任何東西,模組缺失會被回報而不是致命錯誤。只有 C_GetFunctionList 按名稱解析;其餘進入點都來自它傳回的函式表,這也正是標準設計期望的模組存取方式
ConfigurePkcs11SignerProvider 根據一個 TPdfPkcs11Options 值建構 TPdfPkcs11SignerProvider,並將其安裝為目前的 PAdES 簽署器後端,傳回同時攜帶權杖列舉方法的 IPdfPkcs11SignerProvider 介面
Pkcs11ModuleAvailable 與 Pkcs11ModuleVersion 回報給定模組能否載入並公開可用的函式表,應用程式因此可以在啟動時判斷本機能否進行權杖簽署。已載入的模組會以路徑為鍵快取,因為標準允許每個處理程序對每個模組只初始化一次
Resolve 在提供了 TPadesSignerOptions.CertificateThumbprint 時按其選擇憑證,否則按 CertificateLabel 選擇,然後尋找與憑證攜帶相同權杖識別碼的私鑰物件。憑證金鑰演算法決定演算法族:EC 金鑰用 ECDSA 簽章,其原始簽章被重新編碼為 CMS 期望的 DER SEQUENCE;RSA 金鑰則遵循要求的填充方案
EnumerateSlots 與 EnumerateCertificates 服務於選擇類使用者介面,讓應用程式在任何簽署選項確定之前列出模組回報的插槽以及所選插槽中的憑證
| Function | Description |
|---|---|
Pkcs11ModuleAvailable | 當給定路徑的模組能載入並公開可用的函式表時傳回 True |
Pkcs11ModuleVersion | 傳回模組回報的版本字串,模組無法載入時傳回空字串 |
Pkcs11AbiLayout | 傳回本建置解析出的 ABI 佈局,形式為 ulong=<n> attr=<n> pss=<n> table=<n> |
ConfigurePkcs11SignerProvider | 根據給定選項建構提供者,將其安裝為 PAdES 簽署器後端,並作為 IPdfPkcs11SignerProvider 傳回 |
| Type | Purpose |
|---|---|
EPdfPkcs11Error | 當未設定模組路徑、模組無法載入、權杖呼叫失敗,或找不到相符的憑證或私鑰時拋出的例外 |
TPdfPkcs11Options | 記錄提供者使用的模組、插槽、PIN 和憑證 |
TPdfPkcs11SignerProvider | 在 PKCS#11 模組之上實作 IPadesSignerProvider 與 IPdfPkcs11SignerProvider 的提供者類別 |
| Field | Description |
|---|---|
ModulePath | PKCS#11 模組的路徑;必填,因為由哪個模組服務權杖屬於部署決策,沒有有用的預設值 |
SlotId | 要開啟的權杖插槽,僅在 UseSpecificSlot 為 True 時生效 |
UseSpecificSlot | 保持 False 即採用第一個回報權杖在位的插槽 |
Pin | 使用者 PIN;權杖使用完畢後提供者會清除自己的副本,傳入字串的生命週期仍由呼叫端負責 |
CertificateLabel | 用於簽署的憑證的物件標籤,選用,僅在 TPadesSignerOptions.CertificateThumbprint 為空時使用 |
Default | 靜態工廠,傳回模組路徑為空、插槽為 0、自動選擇插槽且無 PIN 與標籤的選項 |
| Member | Description |
|---|---|
Create | 根據 TPdfPkcs11Options 值建構提供者;模組本身在首次使用時開啟 |
Destroy | 在實體釋放之前關閉所有開啟的權杖連線 |
BackendName | 傳回後端名稱,設定了模組路徑時會附加模組檔案名稱 |
Resolve | 將 TPadesSignerOptions 解析為持有權杖簽署器與簽署者憑證 DER 的 TPadesResolvedSigner |
EnumerateSlots | 以 TPdfPkcs11Slots 傳回模組回報的所有插槽,包括沒有權杖在位的插槽 |
EnumerateCertificates | 以 TPdfPkcs11Certificates 傳回一個插槽中持有的憑證,會先在該插槽上開啟連線 |
CloseProtectedSessions | 在發生過登入的地方登出並關閉開啟的連線,把權杖釋放給其他消費端 |
CK_ULONG 遵循 C 的 unsigned long,在 Windows (LLP64) 上是 4 位元組,在 Linux 與 macOS (LP64) 上是 8 位元組;每個控制代碼、計數和屬性型別都是 CK_ULONGPkcs11AbiLayout 回報本建置解析出的佈局,因此不符合可被診斷而不是無聲崩潰:Win32 回報 ulong=4 attr=12 pss=12 table=2,Win64 回報 ulong=4 attr=16 pss=12 table=2,LP64 目標回報 ulong=8 attr=24 pss=24 table=8CertificateLabel 時,權杖上的第一張憑證會被選中,這只適合單憑證權杖,不適合任何正式環境部署