Lewati ke konten
getnextpdf.com

Enterprise edisi

Penandatanganan HSM — Referensi Mendalam

Halaman ini adalah referensi mendalam untuk permukaan penandatanganan HSM NextPDF Enterprise. Halaman ini mencakup tiga tipe publik. NextPDF\Enterprise\Security\Signature\Hsm\Pkcs11Signer menandatangani melalui token PKCS#11 via ekstensi ext-pkcs11. NextPDF\Enterprise\Security\Signature\Hsm\OpenSslCliSigner menandatangani melalui biner openssl dalam sebuah subprocess, untuk kunci yang didukung provider atau engine yang tidak dapat dimuat oleh PHP ext-openssl. NextPDF\Enterprise\Security\Signature\Hsm\Provider\HsmSignerProviderAdapter mengekspos salah satu implementasi konkret sebagai SignerProviderInterface terpadu. Pada setiap jalur, private key tetap berada di dalam batas token; NextPDF menyerahkan byte yang akan ditandatangani dan menerima signature. Jalur post-quantum (signPqs) adalah sebuah preview: dinonaktifkan secara default, tidak membawa klaim kesesuaian, dan tidak memiliki jalur verifikasi yang didukung di validator PDF saat ini. NextPDF tidak memegang sertifikasi apa pun dan tidak memberikannya; dukungan tidak sama dengan kesesuaian, dan kesesuaian tidak sama dengan sertifikasi.

Kapabilitas ini disertakan dalam NextPDF Enterprise (nextpdf/enterprise) dan diaktifkan dengan envelope lisensi tingkat Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.

Ketiga tipe tersebut berada di NextPDF\Enterprise\Security\Signature\Hsm; adapter berada di sub-namespace Provider-nya. Kedua signer mengimplementasikan kontrak Core NextPDF\Contracts\HsmSignerInterface.

SimbolParameterPerilaku defaultMengembalikanMelempar atau gagal denganCatatan
Pkcs11Signer::__construct()string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = nullMembuka pustaka vendor, login ke slot, dan memuat metadata sertifikat dan algoritma kunci dari tokenHsmOperationException ketika ext-pkcs11 tidak ada atau akses token gagalSatu handle modul di-cache per jalur pustaka per proses; PIN dan label adalah #[SensitiveParameter]
Pkcs11Signer::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Menandatangani di token; keluaran ECDSA mentah dikonversi ke DER ECDSA-Sig-Valuestring byte signature mentahHsmOperationException (kunci tidak ditemukan, kegagalan token); InvalidArgumentException (algoritma tidak terpetakan); pengecualian FIPS-gate sebelum penandatanganan ketika enforcer terpasangSet algoritma tertutup; lihat Kontrak perilaku
Pkcs11Signer::signPqs()string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = trueDitolak kecuali $enablePostQuantum telah diatur; mengirim mekanisme PQ PKCS#11 provisionalstring byte signature mentahHsmOperationException (dinonaktifkan, kegagalan token, ketidakcocokan panjang signature); InvalidArgumentException (context melebihi 255 byte)Preview; tidak ada klaim kesesuaian; identifier mekanisme bersifat provisional
Pkcs11Signer::isPostQuantumEnabled()Tidak adaMelaporkan flag opt-in konstruktorboolTidak ada
Pkcs11Signer::getCertificateDer()Tidak adaMengembalikan sertifikat signer yang dibaca dari tokenstring (DER)Tidak adaDimuat sekali saat konstruksi
Pkcs11Signer::getCertificateChainDer()Tidak adaMengembalikan intermediate yang disediakan konstruktorarray<string> (DER)Tidak adaTidak menyertakan sertifikat signer
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 = nullMemverifikasi proc_open, memeriksa biner dan versi, mengurai backend, dan memuat sertifikatHsmOperationException (proc_open dinonaktifkan, file module/config/certificate hilang, kegagalan biner, tidak ada backend); InvalidArgumentException (pin-value di dalam $keyUri)OpenSslCliBackend::Auto lebih memilih provider OpenSSL 3.x, kemudian engine
OpenSslCliSigner::sign()string $data, string $algorithm = 'sha256WithRSAEncryption'Menjalankan openssl dgst dalam sebuah subprocess; PIN berjalan melalui file pin-source 0600 ephemeral secara defaultstring byte signature mentahHsmOperationException (timeout, PIN ditolak, kunci tidak ditemukan, kegagalan memuat module, keluaran kosong, kegagalan pin-file); InvalidArgumentException (algoritma tidak terpetakan); pengecualian FIPS-gate sebelum penandatangananSubprocess dimatikan setelah $timeoutSeconds; stderr disunting sebelum mencapai pesan
OpenSslCliSigner permukaan accessorTidak adaHasil konstruksi read-onlystring / array<string> / OpenSslCliBackendTidak adagetCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion
HsmSignerProviderAdapter::__construct()HsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15Membungkus implementasi konkret HSM sebagai SignerProviderInterfaceTidak adaKonvensi provider id: pkcs11-{module-id}, openssl-cli
HsmSignerProviderAdapter::providerId()Tidak adaMengembalikan id yang disediakan konstruktornon-empty-stringTidak ada
HsmSignerProviderAdapter::supportsAlgorithm()SignatureAlgorithm $algoMemetakan enum ke nama bergaya OpenSSL, lalu mengiris allow-set backendboolTidak adaMenolak algoritma digest-only; id openssl-engine tidak mengiklankan apa pun
HsmSignerProviderAdapter::sign()string $data, ?string $keyVersion = nullMengirim melalui signer yang dibungkus dengan algoritma yang dikonfigurasinon-empty-stringKeyManagementException ($keyVersion non-null); SignatureFailedException (algoritma tidak dapat dipetakan, kegagalan driver, signature kosong)Kontrak SPI fail-closed; setiap error driver muncul sebagai typed
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 function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
public function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): string
public function isPostQuantumEnabled(): bool
public function getCertificateDer(): string
public function getCertificateChainDer(): array
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 function getCertificateDer(): string
public function getCertificateChainDer(): array
public function getPublicKeyAlgorithm(): string
public function getCertificatePem(): string
public function getResolvedBackend(): OpenSslCliBackend
public function getOpensslVersion(): string
public function __construct(private HsmSignerInterface $hsm, private string $providerId, private SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15)
public function providerId(): string
public function supportsAlgorithm(SignatureAlgorithm $algo): bool
public function sign(string $data, ?string $keyVersion = null): string
  • Kustodi kunci. Private key tidak pernah meninggalkan batas token. Pkcs11Signer mendelegasikan operasi ke token; OpenSslCliSigner meneruskan sebuah referensi kunci — sebuah URI PKCS#11 — ke subprocess openssl. Tidak ada signer yang dapat mengekspor kunci.
  • Sesi dan login. Pkcs11Signer men-cache satu handle modul PKCS#11 per jalur pustaka per proses, karena antarmuka token harus diinisialisasi tepat satu kali per proses. Setiap operasi membuka sebuah sesi dan login dengan PIN; login mengautentikasi pengguna sebelum penggunaan private-key apa pun (PKCS#11 v3.1 §5.6.8). Ketika slot melaporkan login yang sudah ada, signer logout dan login kembali, sehingga token yang menuntut PIN baru per operasi menerimanya.
  • Set algoritma (tertutup). Kedua signer menerima tepat: sha256WithRSAEncryption, sha384WithRSAEncryption, sha512WithRSAEncryption; RSASSA-PSS, RSASSA-PSS-SHA256, RSASSA-PSS-SHA384, RSASSA-PSS-SHA512; ecdsa-with-SHA256, ecdsa-with-SHA384, ecdsa-with-SHA512. Pkcs11Signer menerima tambahan ecdsa-raw. Identifier lain apa pun memunculkan InvalidArgumentException — tidak ada algoritma pengganti yang pernah ditandatangani.
  • Pengikatan salt PSS. Untuk setiap varian PSS, panjang salt sama dengan panjang digest — 32, 48, atau 64 byte — dan parameter hash dan MGF sesuai dengan digest yang dipilih. Ini mengikuti struktur parameter-mekanisme PSS, di mana panjang salt biasanya adalah panjang message-hash (PKCS#11 v3.1 §6.1.9). Kedua signer menerapkan pemasangan yang sama, sehingga konfigurasi yang valid pada satu backend valid pada yang lain.
  • Konversi ECDSA. Token mengembalikan signature ECDSA sebagai konkatenasi mentah r dan s yang di-zero-pad (PKCS#11 v3.1 §6.3.1). Pkcs11Signer::sign() mengonversi keluaran itu ke bentuk ECDSA-Sig-Value berkode DER yang diharapkan validator PDF dan OpenSSL. Pemanggil tidak pernah menangani bentuk mentahnya.
  • Pengiriman PIN (jalur CLI). Pada default yang aman, PIN ditulis ke file ephemeral yang dibuat secara eksklusif dengan izin hanya-pemilik, direferensikan melalui atribut pin-source URI PKCS#11, dan di-unlink setelah subprocess keluar. PIN tidak ditempatkan di command line dan tidak diekspor ke environment subprocess dalam mode ini. Dengan $legacyPinDelivery = true, PIN disematkan sebagai pin-value di dalam URI, yang dapat diamati di command line proses; mode ini bersifat opt-in saja.
  • Disiplin subprocess. OpenSslCliSigner men-spawn biner dengan sebuah array argumen — tanpa interpolasi shell — memberlakukan $timeoutSeconds, mematikan subprocess saat kedaluwarsa, dan mengklasifikasikan stderr menjadi error typed. Secret disunting dari stderr sebelum dikutip dalam pesan pengecualian.
  • Semantik adapter. Token HSM tidak memiliki konsep key-version terkelola; kunci pada token adalah versinya. Oleh karena itu HsmSignerProviderAdapter::sign() menolak $keyVersion non-null apa pun dengan KeyManagementException alih-alih mengabaikannya. supportsAlgorithm() mengiris pemetaan enum dengan set yang diterima backend yang dibungkus, sehingga adapter tidak pernah mengiklankan mekanisme yang akan ditolak backend saat penandatanganan. Signature kosong dari driver memunculkan SignatureFailedException.
  • Preview post-quantum. signPqs() dijaga di balik flag konstruktor $enablePostQuantum dan menolak berjalan jika tidak. String context dibatasi hingga 255 byte, sesuai dengan batas context ML-DSA (FIPS 204). Signature yang dikembalikan harus sesuai dengan panjang byte persis dari set parameter Pkcs11PqsAlgorithm yang dipilih, atau panggilan gagal. Identifier mekanisme mengikuti ekstensi PQ PKCS#11 provisional dan belum final. Profil PAdES tidak mengenali suite post-quantum, sebagian besar validator PDF menolak signature semacam itu, dan NextPDF tidak menyediakan jalur verifikasi untuknya. Tidak ada kesesuaian yang diklaim.
  • Mengonstruksi Pkcs11Signer tanpa ext-pkcs11 langsung memunculkan HsmOperationException; ekstensi tersebut tidak disertakan dengan distribusi PHP standar.
  • Label certificate atau private-key yang tidak cocok dengan objek apa pun pada token memunculkan HsmOperationException yang menyebutkan kelas objek yang hilang. Label kunci dapat secara sah berbeda dari label certificate pada beberapa token.
  • Login gagal berulang dapat mengunci PIN di token; token yang memberlakukan kebijakan itu, bukan NextPDF. Token yang kuncinya memerlukan autentikasi pada setiap penggunaan menerima login baru melalui jalur logout-and-retry (PKCS#11 v3.1, semantik always-authenticate).
  • OpenSslCliSigner menolak $keyUri yang sudah berisi pin-value saat konstruksi, fail-closed, karena pengiriman itu akan melewati jalur PIN yang aman.
  • Di Windows, mode pin-file yang aman gagal secara tertutup dengan HsmOperationException: bit izin file tidak dapat membatasi hibah baca ACL di sana, sehingga signer menolak meninggalkan PIN cleartext pada ACL direktori temp. Pengiriman PIN legacy adalah alternatif opt-in yang terdokumentasi untuk host Windows tepercaya.
  • Deteksi otomatis backend memerlukan OpenSSL 3.x untuk jalur provider; LibreSSL tidak pernah teruraikan ke provider. Ketika tidak ada probe provider maupun engine yang berhasil, konstruksi gagal dengan HsmOperationException alih-alih menunda kegagalan hingga waktu penandatanganan.
  • Subprocess yang melebihi $timeoutSeconds dihentikan dan dilaporkan sebagai timeout; subprocess yang keluar dengan bersih dengan keluaran kosong dilaporkan sebagai kegagalan empty-signature. Tidak ada kondisi yang dapat menghasilkan dokumen yang ditandatangani sebagian.
  • Signature post-quantum yang panjang byte-nya tidak cocok dengan set parameter yang dipilih ditolak sebelum dapat mencapai pengkodean CMS.
  • HsmSignerProviderAdapter dengan provider id openssl-engine yang telah dipensiunkan tidak mengiklankan algoritma apa pun, sehingga konfigurasi usang gagal saat pemilihan provider alih-alih saat penandatanganan.

Kedua signer menerima FipsSignatureEnforcer opsional. Ketika satu terpasang, mode FIPS aktif untuk signer tersebut: sign() menolak algoritma signature yang tidak diizinkan atau kunci di bawah batas bawah sebelum penandatanganan token atau subprocess apa pun terjadi. Batas bawah mengikuti tabel signature-generation — modulus RSA di bawah 2048 bit dan order ECDSA di bawah 224 bit tidak diizinkan (NIST SP 800-131A Rev.2 §3 Table 2). Tanpa enforcer, perilaku tidak berubah. Gerbang ini hanya mencakup jalur sign() klasik; signPqs() diatur oleh flag preview-nya sendiri. Ini adalah klaim kapabilitas tentang kode NextPDF: validasi FIPS 140-3 menempel pada modul kriptografis melalui CMVP, yang dalam deployment ini adalah HSM atau provider operator — NextPDF bukan modul tervalidasi, tidak memegang sertifikasi, dan tidak memberikannya.

KlaimStandarKlausa
Login mengautentikasi pengguna ke token sebelum operasi private-key; PIN yang salah menolak akses.PKCS#11 v3.1§5.6.8
Kunci always-authenticate memerlukan login baru per penggunaan; re-autentikasi gagal berulang dapat mengunci PIN.PKCS#11 v3.1CKA_ALWAYS_AUTHENTICATE re-authentication
Signature ECDSA token adalah konkatenasi r‖s mentah; signer mengonversinya ke DER untuk interop PDF.PKCS#11 v3.1§6.3.1
Parameter PSS mengikat hash, MGF, dan panjang salt; signer mengatur salt sama dengan panjang digest.PKCS#11 v3.1§6.1.9
Gerbang FIPS menolak generasi signature dengan RSA di bawah 2048 bit atau order ECDSA di bawah 224 bit.NIST SP 800-131A Rev.2§3 Table 2
String context post-quantum dibatasi hingga 255 byte.FIPS 204HashML-DSA context handling
Validasi FIPS 140-3 menempel pada modul kriptografis melalui CMVP.FIPS 140-3CMVP program scope

Semua klausa diparafrasekan; tidak ada teks normatif yang direproduksi. NextPDF tidak membuat klaim sertifikasi. Signer menyelaraskan perilakunya dengan klausa yang dikutip sebagai sebuah kapabilitas. Apakah signature yang dihasilkan terverifikasi adalah keputusan verifier terhadap trust anchor-nya; keamanan kunci bergantung pada token, HSM, dan operator — bukan pada NextPDF saja.

  • Mekanisme pengiriman PIN mengikuti konvensi pin-source URI PKCS#11 (RFC 7512); RFC tersebut berada di luar korpus yang dikutip, sehingga perilaku di atas didasarkan pada sumber produk, bukan kutipan spesifikasi.

  • Konfirmasikan runtime memuat ext-pkcs11 sebelum mengonstruksi Pkcs11Signer; konstruksi gagal cepat ketika ekstensi tidak ada. Signer CLI memerlukan proc_open diaktifkan dan biner openssl dengan provider atau engine PKCS#11 terpasang.

  • PIN, label certificate, dan label kunci adalah #[SensitiveParameter], sehingga dikecualikan dari stack trace. Sediakan PIN dari secret manager; jangan pernah menuliskannya ke sumber, konfigurasi yang di-commit ke version control, atau log.

  • Konstruksi adalah langkah mahal pada kedua signer: jalur PKCS#11 login dan membaca certificate, dan jalur CLI memeriksa biner dan backend. Konstruksi sekali dan gunakan kembali instance-nya; cache modul per-pustaka membuat konstruksi berulang terhadap pustaka yang sama aman.

  • Bungkus signer dalam HsmSignerProviderAdapter ketika pemanggil bekerja melalui SignerProviderInterface. Teruskan provider id kanonis untuk kelas yang dibungkus — pkcs11-{module-id} atau openssl-cli — sehingga pemeriksaan kapabilitas menggunakan allow-set backend yang benar.

  • Sebelum mengaktifkan preview post-quantum, verifikasi identifier mekanisme firmware token terhadap nilai provisional yang didaftarkan NextPDF; ketidakcocokan gagal saat penandatanganan. Jangan aktifkan preview untuk keluaran PAdES produksi.

  • getResolvedBackend() dan getOpensslVersion() ada untuk pencatatan bukti; simpan keduanya bersama bukti penandatanganan ketika program kepatuhan Anda memerlukan reproduktibilitas.

Halaman ini hanya mendokumentasikan perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefiks tiket berada di luar cakupan.