TPDFlibPKCS11Client

Segurança e assinaturas

Descrição

Carrega um módulo PKCS #11 de fornecedor em runtime e expõe certificados e chaves privadas não registrados nos provedores Windows CSP ou KSP

CKA_ID binário e assina digests já calculados por meio de CKM_RSA_PKCS ou CKM_ECDSAA descoberta explícita com certificado opcional pode selecionar uma chave privada ML-DSA por rótulo ou ID binário, validar seu

A descoberta com certificado opcional pode selecionar uma chave privada ML-DSA por rótulo ou ID binária, validar seu CKA_PARAMETER_SET e assinar mensagens originais por meio de CKM_ML_DSA

SignDigest e assinar mensagens originais por meio de TPDFlibExternalDigestSignEventTPDFlib.OnExternalDigestSign implementa

Unidade

PDFlibPKCS11

Construção e ciclo de vida do módulo

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

ModulePath identifica uma DLL PKCS #11 Win32 ou Win64 que exporta C_GetFunctionList

C_Initialize/C_FinalizeO carregador primeiro solicita

O loader primeiro solicita CKF_OS_LOCKING_OK; módulos que não conseguem fornecer travamento interno são protegidos por um lock de chamada compartilhado, enquanto módulos em conformidade permitem sessões de cliente separadas executarem concorrentemente

UseFunctionList suporta provedores vinculados estaticamente, embutidos ou gerenciados pela aplicação; o chamador deve manter a tabela fornecida viva até UnloadModule ou destruição

Descoberta e conexão de token

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 enumera os slots presentes com nova tentativa limitada quando um evento hot-plug muda a contagem, e TokenCount informa quantos tokens a última atualização encontrouSelecione um token com

SlotID, TokenLabel, TokenSerial ou uma combinação; uma seleção vazia só tem sucesso quando existe exatamente um token presente

TPDFlibPKCS11Token informa a descrição do slot, o fabricante, o rótulo do token, o modelo, o número de série, os sinalizadores e os limites de comprimento do PIN

Parâmetros

CertificateLabelFiltro CKA_LABEL UTF-8 opcional para o objeto de certificado X.509
CertificateIDFiltro CKA_ID binário opcional armazenado em um AnsiString
PrivateKeyLabelFiltro CKA_LABEL UTF-8 opcional para a chave privada de assinatura
PrivateKeyIDCKA_ID binário opcional da chave privada; quando vazio, o ID do certificado é reutilizado
CertificateOptionalAssume False como padrão; quando True, um rótulo ou ID de chave privada é exigido e a descoberta aceita apenas chaves ML-DSA sem certificado X.509

A descoberta padrão exige um certificado e uma chave inequívocos, exige CKA_SIGN=True, valida o DER do certificado e rejeita divergências de tipo RSA/EC; a descoberta com certificado opcional exige uma chave ML-DSA inequívoca e valida o conjunto de parâmetros 44, 65 ou 87

MLDSAParameterSet

O certificado resolvido é exposto por CertificateDER e o ID da chave selecionada por ResolvedPrivateKeyID

Autenticação

UserPINPIN de usuário somente escrita codificado em UTF-8, verificado contra os limites do token e apagado quando substituído ou destruído
UseProtectedAuthenticationPathPassa um PIN nulo quando o token anuncia CKF_PROTECTED_AUTHENTICATION_PATH
ReadWriteSessionAdiciona CKF_RW_SESSION; a assinatura normalmente precisa apenas da sessão serial somente leitura padrão

As chaves com CKA_ALWAYS_AUTHENTICATE=True recebem um login específico de contexto após cada C_SignInit bem-sucedido

ClearPIN sobrescreve e libera o PIN configurado

Assinatura

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;

As assinaturas RSA usam CKM_RSA_PKCS bruto com um DigestInfo DER construído localmente, de modo que o token não calcula o hash do digest PDF uma segunda vezAs assinaturas ECDSA usam

CKM_ECDSA bruto; a saída P1363 do token é retornada inalterada para PDF_EXTERNAL_SIGNATURE_ECDSA_P1363 ou convertida para DER estrito para PDF_EXTERNAL_SIGNATURE_ECDSA_DER

SignMLDSA passa a mensagem original ao CKM_ML_DSA de parte única com parâmetros de mecanismo vazios, selecionando o contexto vazio padrão; ele é independente de SignHash e do callback de digest CMS

Os comprimentos de digest SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384 e SHA3-512 são validados antes de qualquer operação de chave privada

C_SignInit falha antes de a assinatura começar, evitando operações duplicadas de chave privada após uma falha ambígua de C_Sign

Exemplo

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;

Estado e comportamento em caso de falha

Connected, KeyType, MLDSAParameterSet, AlwaysAuthenticate, FunctionListMajor e FunctionListMinor expõem o estado ativo do provedorOs métodos retornam

False e definem tanto LastReturnValue quanto LastError quando o carregamento do módulo, a seleção de token, a autenticação, a descoberta de objetos, os limites de atributos, as verificações de mecanismo ou a assinatura falham

Veja também

OnExternalDigestSign, SetSignProcessExternalDigestSigner, SetSignProcessDigestAlgorithm, TPDFlibCSCClient

Administração de PIN

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

Ambas as operações abrem sua própria sessão de leitura/gravação no token configurado e deixam a sessão de assinatura intacta; InitializeUserPIN entra como o security officer antes de chamar C_InitPIN, e ChangeUserPIN entra como o usuário antes de chamar C_SetPIN

Buffers de PIN são apagados após o uso; um módulo sem o ponto de entrada exigido relata um erro em vez de falhar silenciosamente