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 es el backend de firma PAdES portable y el homólogo del backend CNG de Windows. Resuelve un certificado de firmante y su clave privada desde un token PKCS#11 y devuelve un TPadesResolvedSigner cuyo ICmsSigner produce la firma SignerInfo a través del token, de modo que la clave nunca sale de él
El módulo se carga en tiempo de ejecución por ruta - opensc-pkcs11.so, libsofthsm2.so, una DLL del fabricante - de modo que nada se enlaza en tiempo de compilación y un módulo ausente se informa en lugar de ser fatal. Solo C_GetFunctionList se resuelve por nombre; todos los demás puntos de entrada salen de la tabla de funciones que este devuelve, que es como el estándar prevé llegar a un módulo
ConfigurePkcs11SignerProvider construye un TPdfPkcs11SignerProvider a partir de un valor TPdfPkcs11Options y lo instala como backend de firmantes PAdES activo, devolviendo la interfaz IPdfPkcs11SignerProvider que también incorpora los métodos de enumeración del token
Pkcs11ModuleAvailable y Pkcs11ModuleVersion informan de si un módulo dado se carga y expone una tabla de funciones utilizable, de modo que una aplicación puede decidir al arrancar si la firma con token es posible en esta máquina. Los módulos cargados se almacenan en caché por ruta, porque el estándar solo permite una inicialización por proceso y módulo
Resolve selecciona el certificado por TPadesSignerOptions.CertificateThumbprint cuando se suministra uno y por CertificateLabel en caso contrario, y después localiza el objeto de clave privada que lleva el mismo identificador de token que el certificado. El algoritmo de la clave del certificado decide la familia de algoritmos: una clave EC firma con ECDSA y su firma bruta se recodifica como la SEQUENCE DER que CMS espera, mientras que una clave RSA sigue el esquema de relleno solicitado
EnumerateSlots y EnumerateCertificates sirven a las interfaces de usuario de selección, permitiendo que una aplicación enumere las ranuras que informa un módulo y los certificados que contiene una ranura elegida antes de fijar cualquier opción de firma
| Función | Descripción |
|---|---|
Pkcs11ModuleAvailable | Devuelve True cuando el módulo de la ruta indicada se carga y expone una tabla de funciones utilizable |
Pkcs11ModuleVersion | Devuelve la cadena de versión que informa el módulo, o una cadena vacía cuando el módulo no se carga |
Pkcs11AbiLayout | Devuelve la disposición ABI que resolvió esta compilación, como ulong=<n> attr=<n> pss=<n> table=<n> |
ConfigurePkcs11SignerProvider | Construye un proveedor a partir de las opciones suministradas, lo instala como backend de firmantes PAdES y lo devuelve como IPdfPkcs11SignerProvider |
| Tipo | Propósito |
|---|---|
EPdfPkcs11Error | Excepción que se lanza cuando no hay ninguna ruta de módulo configurada, el módulo no se puede cargar, falla una llamada al token o no se encuentra ningún certificado o clave privada coincidente |
TPdfPkcs11Options | Record que nombra el módulo, la ranura, el PIN y el certificado con los que trabaja el proveedor |
TPdfPkcs11SignerProvider | Clase proveedora que implementa IPadesSignerProvider y IPdfPkcs11SignerProvider sobre un módulo PKCS#11 |
| Campo | Descripción |
|---|---|
ModulePath | Ruta al módulo PKCS#11; obligatoria, porque qué módulo atiende un token es una decisión de despliegue y no existe un valor por omisión útil |
SlotId | Ranura de token que se abrirá, respetada solo cuando UseSpecificSlot es True |
UseSpecificSlot | Déjelo en False para tomar la primera ranura que informe de un token presente |
Pin | PIN de usuario; el proveedor borra su propia copia una vez que el token la ha consumido, y la vida útil de la cadena que se pasa queda en manos de quien llama |
CertificateLabel | Etiqueta de objeto opcional del certificado con el que se firma; se usa solo cuando TPadesSignerOptions.CertificateThumbprint está vacía |
Default | Fábrica estática que devuelve opciones con una ruta de módulo vacía, ranura 0, selección automática de ranura y sin PIN ni etiqueta |
| Miembro | Descripción |
|---|---|
Create | Construye el proveedor a partir de un valor TPdfPkcs11Options; el módulo en sí se abre en el primer uso |
Destroy | Cierra cualquier sesión de token abierta antes de liberar la instancia |
BackendName | Devuelve el nombre del backend, con el nombre del archivo del módulo añadido cuando hay una ruta de módulo configurada |
Resolve | Resuelve TPadesSignerOptions en un TPadesResolvedSigner que contiene el firmante del token y el DER del certificado del firmante |
EnumerateSlots | Devuelve todas las ranuras que informa el módulo como TPdfPkcs11Slots, incluidas las ranuras sin token presente |
EnumerateCertificates | Devuelve los certificados contenidos en una ranura como TPdfPkcs11Certificates, abriendo antes una sesión en esa ranura |
CloseProtectedSessions | Cierra la sesión donde hubo inicio de sesión y cierra la sesión abierta, liberando el token para otros consumidores |
CK_ULONG sigue el unsigned long de C, así que ocupa 4 bytes en Windows (LLP64) y 8 bytes en Linux y macOS (LP64); cada manejador, cada cuenta y cada tipo de atributo es un CK_ULONGPkcs11AbiLayout informa de la disposición que resolvió esta compilación, de modo que una discrepancia es diagnosticable en lugar de un fallo silencioso: Win32 informa ulong=4 attr=12 pss=12 table=2, Win64 informa ulong=4 attr=16 pss=12 table=2, y un destino LP64 informa ulong=8 attr=24 pss=24 table=8CertificateLabel, gana el primer certificado del token, algo que conviene a un token de un solo certificado y a ningún despliegue de producción