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 수명 하나를 공유합니다
로더는 먼저 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 | X.509 인증서 객체의 선택적 UTF-8 CKA_LABEL 필터입니다 |
|---|---|
| CertificateID | AnsiString에 저장되는 선택적 바이너리 CKA_ID 필터입니다 |
| PrivateKeyLabel | 개인 서명 키의 선택적 UTF-8 CKA_LABEL 필터입니다 |
| PrivateKeyID | 선택적 바이너리 개인 키 CKA_ID입니다. 비어 있으면 인증서 ID가 재사용됩니다 |
| CertificateOptional | 기본값은 False입니다. True이면 개인 키 레이블이나 ID가 필요하고 탐색은 X.509 인증서 없는 ML-DSA 키만 받아들입니다 |
기본 탐색은 모호하지 않은 인증서와 키 한 쌍을 요구하고, CKA_SIGN=True를 요구하며, 인증서 DER을 검증하고, RSA/EC 유형 불일치를 거부합니다. 인증서 선택적 탐색은 모호하지 않은 ML-DSA 키를 요구하고 매개변수 집합 44, 65, 87을 검증합니다
해석된 ML-DSA 매개변수 집합은 MLDSAParameterSet으로 노출됩니다
해석된 인증서는 CertificateDER로, 선택된 키 ID는 ResolvedPrivateKeyID로 노출됩니다
인증
| UserPIN | UTF-8으로 인코딩된 쓰기 전용 사용자 PIN이며 토큰 한계와 대조 검증되고 교체되거나 파괴될 때 지워집니다 |
|---|---|
| UseProtectedAuthenticationPath | 토큰이 CKF_PROTECTED_AUTHENTICATION_PATH를 알리면 null PIN을 전달합니다 |
| 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 서명은 로컬에서 만든 DER DigestInfo를 쓰는 원시 CKM_RSA_PKCS를 사용하므로, 토큰이 PDF 다이제스트를 두 번 해싱하지 않습니다
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 버퍼는 사용 후 지워집니다. 필요한 엔트리 포인트가 없는 모듈은 조용히 실패하는 대신 오류를 보고합니다