TPDFlibPKCS11Client

Безопасность и подписи

Описание

Загружает модуль PKCS #11 поставщика во время выполнения и раскрывает сертификаты и закрытые ключи, не зарегистрированные в провайдерах Windows CSP или KSP

CKA_ID и подписывает уже вычисленные дайджесты через CKM_RSA_PKCS или CKM_ECDSAЯвное обнаружение с необязательным сертификатом может выбрать закрытый ключ ML-DSA по метке или бинарному ID, проверить его

Обнаружение с необязательным сертификатом может выбрать закрытый ключ ML-DSA по метке или бинарному идентификатору, проверить его CKA_PARAMETER_SET и подписывать исходные сообщения через CKM_ML_DSA

SignDigest и подписывать исходные сообщения через TPDFlibExternalDigestSignEventTPDFlib.OnExternalDigestSign реализует

Единица

PDFlibPKCS11

Создание и жизненный цикл модуля

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

ModulePath идентифицирует DLL PKCS #11 для Win32 или Win64, экспортирующую C_GetFunctionList

C_Initialize/C_FinalizeЗагрузчик сначала запрашивает

Загрузчик сначала запрашивает 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 или их комбинации; пустой выбор успешен, только когда существует ровно один присутствующий токен

TPDFlibPKCS11Token сообщает описание слота, производителя, метку токена, модель, серийный номер, флаги и границы длины PIN

Параметры

CertificateLabelНеобязательный фильтр UTF-8 CKA_LABEL для объекта сертификата X.509
CertificateIDНеобязательный бинарный фильтр CKA_ID, хранящийся в AnsiString
PrivateKeyLabelНеобязательный фильтр UTF-8 CKA_LABEL для закрытого подписывающего ключа
PrivateKeyIDНеобязательный бинарный CKA_ID закрытого ключа; когда пуст, повторно используется ID сертификата
CertificateOptionalПо умолчанию False; когда True, требуется метка или ID закрытого ключа, а обнаружение принимает только ключи ML-DSA без сертификата X.509

Обнаружение по умолчанию требует однозначных сертификата и ключа, требует CKA_SIGN=True, проверяет DER сертификата и отклоняет несовпадения типов RSA/EC; обнаружение с необязательным сертификатом требует однозначного ключа ML-DSA и проверяет набор параметров 44, 65 или 87

MLDSAParameterSet

Разрешенный сертификат раскрывается через CertificateDER, а идентификатор выбранного ключа — через ResolvedPrivateKeyID

Аутентификация

UserPINPIN пользователя только для записи, закодированный в UTF-8, проверяемый по границам токена и стираемый при замене или уничтожении
UseProtectedAuthenticationPathПередаёт нулевой PIN, когда токен объявляет CKF_PROTECTED_AUTHENTICATION_PATH
ReadWriteSessionДобавляет CKF_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 используют сырой CKM_RSA_PKCS с локально построенным DER DigestInfo, поэтому токен не хеширует дайджест PDF второй разПодписи ECDSA используют сырой

CKM_ECDSA; вывод P1363 токена возвращается без изменений для PDF_EXTERNAL_SIGNATURE_ECDSA_P1363 или конвертируется в строгий DER для PDF_EXTERNAL_SIGNATURE_ECDSA_DER

SignMLDSA передает исходное сообщение в однопартовый CKM_ML_DSA с пустыми параметрами механизма, выбирая пустой контекст по умолчанию; он независим от SignHash и callback дайджеста 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 стираются после использования; модуль без требуемой точки входа сообщает об ошибке вместо беззвучного сбоя

Буферы PIN стираются после использования; модуль без требуемой точки входа сообщает об ошибке вместо тихого отказа