TPDFlibPKCS11Client

Zabezpečení a podpisy

Popis

Za běhu načte modul PKCS #11 od dodavatele a vystaví certifikáty a soukromé klíče, které nejsou registrovány u poskytovatelů Windows CSP nebo KSP

Klient vypočítá přítomné tokeny, otevře trvalou relaci, autentizuje uživatele, spáruje certifikát X.509 s podpisovým klíčem podle binárního CKA_ID a podepisuje už vypočítané digesty přes CKM_RSA_PKCS nebo CKM_ECDSA

Explicitní objevování s volitelným certifikátem může vybrat soukromý klíč ML-DSA podle štítku nebo binárního ID, ověřit jeho CKA_PARAMETER_SET a podepisovat původní zprávy přes CKM_ML_DSA

SignDigest implementuje TPDFlibExternalDigestSignEvent a lze jej přiřadit přímo na TPDFlib.OnExternalDigestSign

Jednotka

PDFlibPKCS11

Konstrukce a životní cyklus modulu

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

ModulePath identifikuje DLL PKCS #11 pro Win32 nebo Win64 exportující C_GetFunctionList

Klienti používající stejnou cestu sdílejí jeden načtený modul a jednu vyváženou životnost C_Initialize/C_Finalize

Načtač nejdřív požaduje CKF_OS_LOCKING_OK; moduly, které nemohou poskytnout interní zamykání, chrání sdílený zámek volání, zatímco vyhovující moduly dovolejí samostatným klientským relacím běžet souběžně

UseFunctionList podporuje poskytovatele staticky linkované, vložené nebo spravované aplikací; volající musí udržet dodanou tabulku naživu do UnloadModule nebo zničení

Vyhledání a připojení tokenu

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 vytvoří výčet přítomných slotů s omezeným počtem opakování, když událost hot-plug změní jejich počet, a TokenCount hlásí, kolik tokenů poslední obnovení našloVyberte token pomocí

SlotID, TokenLabel, TokenSerial nebo jejich kombinace; prázdný výběr uspěje jen tehdy, existuje-li právě jeden přítomný token

TPDFlibPKCS11Token poskytuje popis slotu, výrobce, label tokenu, model, sériové číslo, příznaky a meze délky PIN

Parametry

CertificateLabelVolitelný filtr UTF-8 CKA_LABEL pro objekt certifikátu X.509
CertificateIDVolitelný binární filtr CKA_ID uložený v AnsiString
PrivateKeyLabelVolitelný filtr UTF-8 CKA_LABEL pro soukromý podpisový klíč
PrivateKeyIDVolitelné binární CKA_ID soukromého klíče; když je prázdné, znovu se použije ID certifikátu
CertificateOptionalVýchozí je False; když True, vyžaduje se štítek nebo ID soukromého klíče a objevování přijímá jen klíče ML-DSA bez certifikátu X.509

Výchozí objevování vyžaduje jeden jednoznačný certifikát a klíč, vyžaduje CKA_SIGN=True, ověřuje DER certifikátu a odmítá nesoulady typů RSA/EC; objevování s volitelným certifikátem vyžaduje jednoznačný klíč ML-DSA a ověřuje sadu parametrů 44, 65 nebo 87

Rozlišená sada parametrů ML-DSA je vystavena přes MLDSAParameterSet

Rozlišený certifikát je vystaven přes CertificateDER a vybrané ID klíče přes ResolvedPrivateKeyID

Ověřování

UserPINUživatelský PIN pouze pro zápis, kódovaný v UTF-8, kontrolovaný vůči mezím tokenu a vymazávaný při nahrazení nebo zničení
UseProtectedAuthenticationPathPředá prázdný PIN, když token hlásí CKF_PROTECTED_AUTHENTICATION_PATH
ReadWriteSessionPřidává CKF_RW_SESSION; podepisování obvykle vyžaduje pouze výchozí sériovou relaci jen pro čtení

Klíče s CKA_ALWAYS_AUTHENTICATE=True dostávají kontextově specifické přihlášení po každém úspěšném C_SignInit

ClearPIN přepíše a uvolní nastavený PIN

Podepisování

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;

Podpisy RSA používají surový CKM_RSA_PKCS s lokálně postaveným DigestInfo v DER, takže token nehází PDF digest podruhé

Podpisy ECDSA používají surový CKM_ECDSA; výstup P1363 z tokenu se vrací nezměněn pro PDF_EXTERNAL_SIGNATURE_ECDSA_P1363 nebo převádí na striktní DER pro PDF_EXTERNAL_SIGNATURE_ECDSA_DER

SignMLDSA předává původní zprávu do jednodílného CKM_ML_DSA s prázdnými parametry mechanismu a volí výchozí prázdný kontext; je nezávislá na SignHash a zpětném volání digestu CMS

Délky digestů SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384 a SHA3-512 se ověří před jakoukoli operací se soukromým klíčem

Ztracená relace se znovu otevře a zopakuje jen tehdy, když C_SignInit selže před zahájením podpisování, čímž se zabrání duplicitním operacím se soukromým klíčem po nejednoznačném selhání C_Sign

Příklad

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;

Stav a chování při selhání

Connected, KeyType, MLDSAParameterSet, AlwaysAuthenticate, FunctionListMajor a FunctionListMinor zpřístupňují stav aktivního poskytovateleMetody vrací

False a nastaví LastReturnValue i LastError, když selže načtení modulu, výběr tokenu, autentizace, vyhledávání objektů, meze atributů, kontroly mechanismů nebo podepisování

Viz také

OnExternalDigestSign, SetSignProcessExternalDigestSigner, SetSignProcessDigestAlgorithm, TPDFlibCSCClient

Správa PIN

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

Obě operace si otevřou vlastní relaci čtení/zápisu na nakonfigurovaném tokenu a nechají relaci podpisování nedotčenou; InitializeUserPIN se přihlásí jako bezpečnostní důstojník před voláním C_InitPIN, ChangeUserPIN se přihlásí jako uživatel před voláním C_SetPIN

Buffery PIN se po použití vymažou; modul bez požadovaného vstupního bodu nahlásí chybu, místo aby tiše selhal