Aller au contenu
getnextpdf.com

Enterprise édition

Sécurité — référence approfondie (HSM, PKCS#11, mode FIPS)

Cette page est la référence approfondie combinée de la surface de sécurité de NextPDF Enterprise. Elle couvre la signature par jeton matériel via PKCS#11, la signature en sous-processus via l’interface en ligne de commande (CLI) d’OpenSSL, les préréglages de politique cryptographique FIPS, le garde FIPS à l’exécution et le garde d’autotest à la mise sous tension. Deux compléments ciblés existent : HSM — référence approfondie pour le détail des signataires et FIPS 140 — référence approfondie pour le détail du module FIPS. Le chemin de signature post-quantique est un aperçu sans revendication de conformité. NextPDF ne détient aucune certification et n’en accorde aucune ; la prise en charge n’équivaut pas à la conformité, et la conformité n’équivaut pas à la certification.

Cette capacité est livrée dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de niveau Enterprise. Un déploiement dépourvu de ce droit ne charge pas les classes de la capacité. Comparer les éditions et obtenir une licence.

Fenêtre de terminal
composer require nextpdf/enterprise:^3

Les types de signature résident dans NextPDF\Enterprise\Security\Signature\Hsm ; les types FIPS résident dans NextPDF\Enterprise\Security\Fips ; la racine de composition réside dans NextPDF\Enterprise\Bootstrap. Les deux signataires implémentent le contrat Core NextPDF\Contracts\HsmSignerInterface. La politique implémente les contrats Core NextPDF\Contracts\CryptoPolicyInterface et NextPDF\Contracts\PreOperationalSelfTestInterface.

SymboleParamètresComportement par défautRetourneLève ou échoue avecNotes
Pkcs11Signer::__construct()string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = nullOuvre la bibliothèque du fournisseur, se connecte au slot, charge le certificat et les métadonnées d’algorithme de cléHsmOperationException lorsque ext-pkcs11 est absent ou que l’accès au jeton échoueLe PIN et les libellés sont #[SensitiveParameter] ; un handle de module est mis en cache par chemin de bibliothèque et par processus
Pkcs11Signer::isAvailable()AucunIndique si ext-pkcs11 est chargéboolAucunStatique ; à vérifier avant la construction
Pkcs11Signer::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Signe sur le jeton ; la sortie ECDSA brute est convertie en ECDSA-Sig-Value DERstring octets de signature brutsHsmOperationException (clé introuvable, échec du jeton) ; InvalidArgumentException (algorithme non mappé) ; FipsViolationException / FipsModuleErrorStateException avant la signature lorsqu’un enforcer est câbléEnsemble d’algorithmes fermé ; voir le contrat de comportement
Pkcs11Signer::signPqs()string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = trueRefusé sauf si $enablePostQuantum a été activé ; distribue le mécanisme post-quantique provisoire de PKCS#11string octets de signature brutsHsmOperationException (désactivé, échec du jeton, longueur de signature incohérente) ; InvalidArgumentException (contexte de plus de 255 octets)Aperçu ; aucune revendication de conformité
Pkcs11Signer surface d’accesseursAucunRésultats de construction en lecture seulebool / string / array<string>AucunisPostQuantumEnabled, getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm
OpenSslCliSigner::__construct()string $keyUri, string $certPath, string $pin, array $extraCertPaths = [], OpenSslCliBackend $backend = OpenSslCliBackend::Auto, string $opensslBinary = 'openssl', int $timeoutSeconds = 30, ?string $modulePath = null, ?string $configPath = null, bool $legacyPinDelivery = false, ?FipsSignatureEnforcer $fipsEnforcer = nullVérifie proc_open, sonde le binaire, résout le backend, charge les certificatsHsmOperationException (proc_open désactivé, fichier de module/configuration/certificat manquant, aucun backend) ; InvalidArgumentException (pin-value dans $keyUri)Auto privilégie le fournisseur OpenSSL 3.x, puis le moteur
OpenSslCliSigner::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Signe dans un sous-processus openssl ; par défaut, le PIN transite par un fichier pin-source éphémère 0600string octets de signature brutsHsmOperationException (délai dépassé, PIN rejeté, clé introuvable, sortie vide) ; InvalidArgumentException (algorithme non mappé) ; exceptions de barrière FIPS avant la signatureLe sous-processus est tué après $timeoutSeconds ; stderr est expurgé
OpenSslCliSigner surface d’accesseursAucunRésultats de construction en lecture seulestring / array<string> / OpenSslCliBackendAucungetCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion
OpenSslCliBackendÉnumération : Provider, Engine, AutoAucunSélection du backend pour le signataire CLI
Pkcs11PqsAlgorithmÉnumération des jeux de paramètres ML-DSA et SLH-DSAAucunAssistants : isMlDsa, isSlhDsa, mechanismId, parameterSetId, signatureLength, nistCategory
PqsCapabilityStatus::current()AucunConstruit la posture post-quantique honnête pour le processusPqsCapabilityStatusAucunChaque booléen de revendication de conformité est codé en dur à false ; aucun indicateur ne peut en activer un
HsmSignerProviderAdapterHsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15Expose une implémentation HSM concrète en tant que SignerProviderInterface unifiéSelon le SPIKeyManagementException (version de clé non nulle) ; SignatureFailedException (échec du pilote, signature vide)Identifiants de fournisseur : pkcs11-{module-id}, openssl-cli
HsmOperationExceptionÉchec typé pour chaque chemin de signature HSMÉtend le NextPdfException de Core
FipsCryptoPolicy::strict() / ::standard()?FipsSelfTest $selfTest = nullPréréglages de fabrique ; strict est le profil FIPS 140-3, standard ajoute AES-128-CBCFipsCryptoPolicyAucunListes d’autorisation immuables ; voir le comportement en mode FIPS
FipsCryptoPolicy surface de prédicatsentrées string / intVérifications d’appartenance à la liste d’autorisationbool / stringAucunisHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName
FipsCryptoPolicy::assertPreOperational()AucunExécute (ou rejoue) l’autotest à la mise sous tensionvoidFipsModuleErrorStateExceptionPiloté par la couture d’application de Core lors de la première opération cryptographique
FipsModeGuard::__construct()CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = nullEnveloppe une politique avec des limites de type assertionAucunSans garde de démarrage, la barrière d’autotest est absente (politique seule)
FipsModeGuard surface d’assertionsentrées string / intCatalogue de refus d’abord, puis liste d’autorisation ; enregistrement d’audit avant toute levéevoidFipsViolationException ; FipsModuleErrorStateException (garde de démarrage câblé)assertHashAllowed, assertSignatureAlgorithmAllowed, assertEncryptionAllowed, assertKeyStrengthAllowed, ainsi que getPolicy
FipsBootGuard::report() / ::rerun()AucunExécute la batterie d’autotests (en cache / forcée)FipsSelfTestReportAucunUn rapport ERROR verrouille le processus ; une réexécution réussie n’efface jamais le verrou
FipsBootGuard::assertOperational()AucunAffirme que le module est OPERATIONALvoidFipsModuleErrorStateExceptionPersistant : un ERROR verrouillé au niveau du processus rejette même une instance propre
FipsBootGuard::status()AucunIndique le statut en cacheFipsSelfTestStatusAucunPRE_OPERATIONAL, OPERATIONAL ou ERROR
FipsSelfTest::run()AucunExécute la batterie complète de tests à réponse connue ; ne court-circuite jamaisFipsSelfTestReportAucunLe constructeur accepte des fournisseurs injectables de hachage et d’octets aléatoires pour des tests déterministes
FipsSelfTestReport / FipsSelfTestResult / FipsSelfTestStatusObjets valeur de rapport et énumération de statutFipsSelfTestReport::assertOperational() lève FipsModuleErrorStateExceptionresults liste toujours chaque résultat comme preuve d’audit
FipsSignatureEnforcer::assertSignatureGenerationAllowed()string $algorithm, string $certificatePemRésout l’OID de signature et la robustesse de la clé, puis délègue au gardevoidFipsViolationException (interdit ou non classable, fermeture sûre)Le point de passage obligé que les deux signataires appellent en tête de sign() en mode FIPS
FipsAuditLoggerCryptoPolicyInterface $policy, LoggerInterface $loggerÉmet des enregistrements ALLOW (INFO) / DENY (WARNING) par décisionbool par appel de journalisationAucunlogHashOperation, logSignatureOperation, logEncryptionOperation, logKeyStrengthCheck
FipsTransitioningAlgorithmsentrées string / intCatalogue de refus statique NIST SP 800-131Abool / arrayAucunLa couche de refus explicite sous chaque limite de garde
FipsBootstrap::boot() / ::lazy()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = nullCompose le garde de démarrage, la politique et le garde de mode ; boot() exécute l’autotest immédiatement, lazy() le diffère jusqu’à la première limiteFipsModeGuardboot() : FipsModuleErrorStateException en cas d’échec du testPar défaut, la politique stricte
FipsBootstrap::signatureEnforcer()?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = nullDémarre le module et retourne la barrière au moment de la génération pour les signatairesFipsSignatureEnforcerFipsModuleErrorStateExceptionPasse le résultat au paramètre $fipsEnforcer d’un signataire
FipsBootstrap::selfTestReport()?FipsSelfTest $selfTest = nullExécute la batterie à la demande et la résumearray{status, operational, failed}AucunDestiné aux endpoints de santé et à la sous-commande CLI
FipsViolationException / FipsModuleErrorStateExceptionÉchecs FIPS typésExposent respectivement policyName / violatingItem / reason et failedResults
public function __construct(private readonly string $libraryPath, private readonly int $slotId, #[SensitiveParameter] private readonly string $pin, #[SensitiveParameter] private readonly string $certLabel, #[SensitiveParameter] private readonly ?string $keyLabel = null, array $chainDer = [], private readonly bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null)
public static function isAvailable(): bool
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): string
public function __construct(private string $keyUri, string $certPath, #[SensitiveParameter] private string $pin, array $extraCertPaths = [], private OpenSslCliBackend $backend = OpenSslCliBackend::Auto, private string $opensslBinary = 'openssl', private int $timeoutSeconds = 30, private ?string $modulePath = null, private ?string $configPath = null, private bool $legacyPinDelivery = false, private ?FipsSignatureEnforcer $fipsEnforcer = null)
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public static function strict(?FipsSelfTest $selfTest = null): self
public static function standard(?FipsSelfTest $selfTest = null): self
public function assertPreOperational(): void
public function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)
public function assertHashAllowed(string $algorithm): void
public function assertSignatureAlgorithmAllowed(string $oid): void
public function assertEncryptionAllowed(string $algorithm): void
public function assertKeyStrengthAllowed(string $keyType, int $bitLength): void
public function getPolicy(): CryptoPolicyInterface
public static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuard
public static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcer
public static function selfTestReport(?FipsSelfTest $selfTest = null): array
  • Résolution des contrats. Les deux signataires implémentent le HsmSignerInterface de Core ; la politique implémente le CryptoPolicyInterface de Core. Le code appelant dépend des contrats, de sorte qu’une montée de version d’édition change la composition, pas les sites d’appel.
  • Garde des clés. La clé privée ne quitte jamais la frontière du jeton. Pkcs11Signer délègue l’opération au jeton ; OpenSslCliSigner transmet au sous-processus une référence de clé sous forme d’URI PKCS#11. NextPDF ne stocke, ne génère ni ne garantit la sécurité de la clé de signature. La protection des clés relève de la responsabilité de garde de l’opérateur (NIST SP 800-57 Part 1 Rev.5 §5.5.2).
  • Session et connexion. L’opération de signature du jeton, la session et la connexion de l’utilisateur suivent PKCS#11 v3.1 §5. Le libellé du certificat et le libellé de la clé privée peuvent différer ; le constructeur accepte un libellé de clé distinct pour de tels jetons.
  • Ensemble d’algorithmes fermé. Les signataires acceptent exactement : RSA PKCS#1 v1.5 avec SHA-256/384/512, RSASSA-PSS avec SHA-256/384/512 et ECDSA avec SHA-256/384/512 (Pkcs11Signer accepte également ecdsa-raw). Tout autre identifiant lève InvalidArgumentException ; aucun algorithme de substitution n’est jamais signé.
  • Liaison du sel PSS. Pour chaque variante PSS, la longueur du sel est égale à la longueur du condensé — 32, 48 ou 64 octets — et les paramètres de hachage et de génération de masque correspondent au condensé choisi (PKCS#11 v3.1 §5).
  • Conversion ECDSA. Les mécanismes ECDSA du jeton retournent une signature brute ; sign() la convertit sous la forme ECDSA-Sig-Value encodée en DER pour l’interopérabilité avec le PDF et OpenSSL. La génération de signature suit FIPS 186-5 §6.3.2.
  • Contenu des préréglages. Le préréglage strict autorise SHA-256/384/512 ; les OID de signature RSA et ECDSA avec ces hachages ; RSASSA-PSS ; AES-256-CBC et AES-256-GCM ; RSA 2048 et EC 256 au minimum. Le préréglage standard autorise en plus AES-128-CBC pour l’interopérabilité héritée. Tout usage d’AES-GCM requiert un vecteur d’initialisation unique par clé (NIST SP 800-38D §5).
  • Application à deux couches. Chaque limite de garde consulte d’abord le catalogue de refus explicite NIST SP 800-131A, puis la liste d’autorisation de la politique. La couche de refus produit le signal « interdit » explicite pour l’audit ; la liste d’autorisation reste faisant autorité.
  • Autotest à la mise sous tension. La batterie couvre SHA-256/384/512, HMAC-SHA-256, AES-256-CBC, AES-256-GCM, un test de cohérence par paire ECDSA P-256 et un contrôle de santé de bits aléatoires. La première opération cryptographique sous la politique sur le chemin Core l’exécute une fois par processus, à fermeture sûre. Un échec place le module dans l’état ERROR ; les services cryptographiques sont refusés jusqu’à la réinitialisation. Cela suit ISO/IEC 19790:2025 §7.10, §7.10.2, §7.10.3 et §7.10.3.p3.
  • État ERROR persistant. Un ERROR observé se verrouille pour l’ensemble du processus. Construire une nouvelle politique ou un nouveau garde de démarrage ne peut pas le blanchir ; une réexécution réussie ne l’efface pas. Seul un redémarrage du processus — un véritable cycle d’alimentation — réinitialise l’état.
  • Barrière de génération uniquement. FipsSignatureEnforcer régit la production de nouvelles signatures. La validation de signatures préexistantes est un usage hérité et ne passe jamais par l’enforcer.
  • Piste d’audit. Lorsqu’un garde est composé avec un journaliseur d’audit, chaque limite émet un enregistrement ALLOW ou DENY avant d’autoriser ou de rejeter l’opération. Le journaliseur consulte la même politique que celle appliquée par le garde, de sorte que la décision enregistrée ne peut pas diverger.
  • Construire Pkcs11Signer sans ext-pkcs11 lève HsmOperationException immédiatement ; l’extension n’est pas fournie avec les distributions PHP standard.
  • Un libellé de certificat ou de clé privée qui ne correspond à aucun objet du jeton lève HsmOperationException en nommant la classe d’objet manquante.
  • OpenSslCliSigner refuse à la construction un $keyUri contenant pin-value, à fermeture sûre ; le PIN transite plutôt par le chemin sécurisé pin-source.
  • En mode FIPS, un identifiant d’algorithme qui ne peut pas être mappé à un OID de signature connu est refusé à fermeture sûre ; de même pour un certificat dont la robustesse de clé publique ne peut pas être déterminée.
  • Un type de clé inconnu est refusé par défaut ; la politique ne se rabat jamais sur un algorithme plus faible.
  • Un test à réponse connue échoué lève FipsModuleErrorStateException en portant les résultats en échec ; chaque limite ultérieure du processus répète l’échec jusqu’au redémarrage.
  • Un garde construit sans garde de démarrage applique les listes d’autorisation mais ne fournit aucune barrière d’autotest ; la composition FIPS de production en fournit une via le bootstrap.
  • signPqs() refuse de s’exécuter sauf si l’activation au constructeur a été définie. Une chaîne de contexte de plus de 255 octets lève InvalidArgumentException (FIPS 204 §5.4). Une signature retournée dont la longueur en octets ne correspond pas au jeu de paramètres sélectionné est rejetée avant d’atteindre l’encodage.

Autorisé par FIPS en mode strict : SHA-256/384/512 ; RSA PKCS#1 v1.5 et RSA-PSS avec ces hachages ; ECDSA avec ces hachages ; AES-256-CBC et AES-256-GCM ; RSA d’au moins 2048 bits, EC d’au moins 256 bits. Rejeté par FIPS en mode strict : les hachages plus faibles ou hérités, les OID de signature non approuvés, AES-128 (autorisé uniquement dans le préréglage standard) et toute clé en dessous de la robustesse minimale. La longueur minimale de clé RSA et le statut de transition suivent NIST SP 800-131A Rev.2 §3. L’appariement de courbe et de hachage ECDSA suit FIPS 186-5 §6.1.1. Le chemin est à fermeture sûre et ne substitue jamais un algorithme plus faible.

NextPDF Enterprise n’est pas un module cryptographique validé FIPS et ne formule aucune revendication de certification FIPS. NextPDF Enterprise fonctionne dans un mode compatible FIPS uniquement lorsqu’il est configuré avec un fournisseur cryptographique validé FIPS — par exemple un fournisseur OpenSSL validé FIPS — ou un HSM validé FIPS. La politique de mode FIPS assiste la conformité ; elle n’est pas une certification. Aucun artefact de certification FIPS n’existe dans ce dépôt.

RevendicationNormeClause
Sémantique de l’opération de signature du jeton, de la session et de la connexion utilisateurPKCS#11 v3.1§5 (sign)
La longueur du sel PSS est égale à la longueur du condenséPKCS#11 v3.1§5 (PSS sLen)
Génération de signature ECDSA ; appariement de courbe et de hachageFIPS 186-5§6.3.2; §6.1.1
Longueur minimale de clé RSA et statut de transition de la génération de signatureNIST SP 800-131A Rev.2§3
Catégorie d’autotest, documentation, déclencheur conditionnel, ensemble disjointISO/IEC 19790:2025§7.10, §7.10.2, §7.10.3, §7.10.3.p3
Unicité du vecteur d’initialisation AES-GCMNIST SP 800-38D§5
Responsabilités de protection et de garde des clésNIST SP 800-57 Part 1 Rev.5§5.5.2
Chaîne de contexte de signature post-quantique limitée à 255 octetsFIPS 204§5.4

Toutes les clauses sont paraphrasées ; aucun texte normatif n’est reproduit. Il s’agit de revendications de capacité concernant le code de NextPDF, non de certifications. Le fait qu’une signature produite soit vérifiée relève de la décision du vérificateur au regard de sa propre configuration de confiance. La politique de mode FIPS est une fonctionnalité d’assistance à la conformité, non un avis juridique ; consulte tes propres conseillers en conformité et juridiques. Ce module concerne des fonctionnalités cryptographiques ; traite-le comme sensible du point de vue de la sécurité dans ta propre revue.

  • Compose le mode FIPS via le bootstrap : boot() pour une barrière au démarrage, lazy() pour différer la batterie jusqu’à la première limite, et la fabrique d’enforcer pour le paramètre $fipsEnforcer des signataires. Les déploiements non-FIPS passent null et le comportement est inchangé.
  • La sous-commande fips:self-test de bin/nextpdf-enterprise exécute la batterie à la demande et sort avec un code non nul dans l’état ERROR ; branche-la sur des tâches de maintenance ou des endpoints de santé réservés aux administrateurs (autotests à la demande d’ISO/IEC 19790:2025).
  • FipsBootGuard::resetProcessErrorLatchForTesting() est @internal et réservé aux tests ; le code de production ne l’appelle jamais, car cela mettrait en échec l’état ERROR persistant.
  • Construis les signataires une fois et réutilise-les ; la construction se connecte et lit le certificat, et le cache de module par bibliothèque rend sûre la construction répétée contre la même bibliothèque.
  • Fournis le PIN depuis un gestionnaire de secrets. Il s’agit d’un #[SensitiveParameter], jamais journalisé ni sérialisé ; ne le committe pas dans la configuration.
  • L’opérateur est responsable du provisionnement du jeton, de la gestion du PIN, de la configuration du slot, de la protection réseau d’un HSM connecté au réseau et de la configuration de confiance. Cette page n’expose pas les rouages internes de la politique de PIN du jeton ni le matériel d’identification du fournisseur.
  • N’active pas l’aperçu post-quantique pour les signatures AdES de production. Le catalogue des suites cryptographiques AdES ne reconnaît pas encore les suites post-quantiques, la plupart des lecteurs PDF rejettent de telles signatures, et la validation matérielle aller-retour n’est pas achevée. Le détail interne des mécanismes reste dans la documentation interne du dépôt source et sort du périmètre de ce manuel.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins de namespace internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de ticket sortent du périmètre.