Lewati ke konten

Kontrak penyedia KMS

HsmSignerInterface adalah kontrak publik yang diimplementasikan pihak ketiga untuk menyediakan penyimpanan kunci bagi NextPDF. Penyedia Anda menyimpan private key; engine membangun struktur Cryptographic Message Syntax (CMS).

Terminal window
composer require nextpdf/core:^3

NextPDF memisahkan perakitan tanda tangan dari penyimpanan kunci. Engine menyiapkan rentang byte dan merakit struktur CMS SignedData. Engine tidak menyimpan private key. Sebagai gantinya, engine mendelegasikan penyimpanan kunci kepada back end penandatanganan melalui kontrak publik.

Anda mengimplementasikan salah satu dari tiga kontrak publik:

  • SignerInterface. Kontrak dasar. Kontrak ini mengembalikan SignatureResult untuk data yang diberikan, menerapkan timestamp, dan melaporkan dukungan long-term validation. Gunakan kontrak ini saat logika penandatanganan berjalan di dalam proses.
  • HsmSignerInterface. Kontrak penyimpanan kunci. Implementasi harus melakukan penandatanganan di dalam batas perangkat keras. Private key tidak boleh meninggalkan batas tersebut. Penyedia key management system mengimplementasikan kontrak ini.
  • DeferredSignerInterface. Perluasan SignerInterface untuk back end asinkron. Pemanggil mengirimkan data, menerima identifier pekerjaan, lalu mengambil hasilnya kemudian.

Halaman ini menetapkan kontrak publik. Halaman ini tidak menjelaskan implementasi internal NextPDF Pro atau NextPDF Enterprise apa pun. Edisi berbayar dapat menyediakan implementasi terdukung untuk kontrak ini. Anda bergantung pada kontrak, bukan pada implementasinya.

Kontrak ini mewajibkan private key tidak pernah meninggalkan batas aman. Praktik manajemen kunci yang mapan mendukung persyaratan ini. National Institute of Standards and Technology (NIST) SP 800-57 Part 1 Revision 5 memperlakukan manajemen kunci sebagai penanganan siklus hidup untuk pembuatan, penyimpanan, distribusi, penggunaan, dan penghancuran yang aman. Public-Key Cryptography Standards #11 (PKCS#11) v3.1 membuat batas tersebut dapat ditegakkan. Ketika objek private key menetapkan CKA_SENSITIVE menjadi true atau CKA_EXTRACTABLE menjadi false, token tidak boleh mengungkapkan nilai kunci dalam bentuk plaintext di luar token.

Implementasi Anda bertanggung jawab untuk memenuhi persyaratan ini. Engine tidak dapat menegakkannya untuk Anda. Jika metode sign() Anda dapat membaca byte kunci mentah ke memori proses, kontrak ini kehilangan properti keamanannya.

NextPDF\Contracts\HsmSignerInterface (stable, sejak 1.0.0):

MetodeMengembalikanTujuan
sign(string $data, string $algorithm)stringTandatangani data di dalam batas perangkat keras. Kembalikan byte tanda tangan mentah. Lemparkan RuntimeException saat gagal.
getCertificateDer()stringKembalikan sertifikat X.509 penanda tangan dalam bentuk Distinguished Encoding Rules (DER).
getCertificateChainDer()array<string>Kembalikan sertifikat antara, dari penerbit hingga root, tidak termasuk sertifikat penanda tangan.
getPublicKeyAlgorithm()stringKembalikan identifier algoritma public key.

NextPDF\Contracts\SignerInterface (stable, sejak 1.0.0):

MetodeMengembalikanTujuan
sign(string $data)SignatureResultKembalikan CMS SignedData yang dikodekan DER.
timestamp(string $signatureValue)stringKembalikan token time-stamp Request for Comments (RFC) 3161 yang dikodekan DER.
supportsLtv()boolLaporkan apakah data long-term validation (LTV) dapat disematkan.

NextPDF\Contracts\DeferredSignerInterface (experimental, sejak 3.0.0) memperluas SignerInterface dengan submitForSigning(), retrieveSignature(), dan isComplete() untuk back end asinkron.

Level tanda tangan yang dihasilkan engine mengikuti profil PDF Advanced Electronic Signatures (PAdES). European Telecommunications Standards Institute (ETSI) EN 319 142-2 mendefinisikan profil PAdES yang diperluas dan dibangun di atas blok penyusun dasar pada EN 319 142-1. Engine memetakan level B-B, B-T, B-LT, dan B-LTA ke blok-blok penyusun tersebut. Signer Anda menyediakan operasi kriptografis dan material sertifikat yang dibutuhkan engine.

Penyedia minimal bergaya PKCS#11 ini mendelegasikan penandatanganan ke token. PHP tidak pernah membaca nilai kunci.

<?php
declare(strict_types=1);
use NextPDF\Contracts\HsmSignerInterface;
final class TokenSigner implements HsmSignerInterface
{
public function __construct(private readonly TokenSession $session) {}
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
{
// The token computes the signature. The key stays inside the token.
return $this->session->c_sign($data, $algorithm);
}
public function getCertificateDer(): string
{
return $this->session->readCertificate();
}
/** @return array<string> */
public function getCertificateChainDer(): array
{
return $this->session->readChain();
}
public function getPublicKeyAlgorithm(): string
{
return 'rsaEncryption';
}
}

Penyedia produksi memvalidasi input, gagal secara tertutup saat terjadi kesalahan token, dan tidak pernah mencatat material kunci maupun tanda tangan.

<?php
declare(strict_types=1);
use NextPDF\Contracts\HsmSignerInterface;
use Psr\Log\LoggerInterface;
use RuntimeException;
final class KmsSigner implements HsmSignerInterface
{
public function __construct(
private readonly RemoteKmsClient $kms,
private readonly string $keyId,
private readonly LoggerInterface $logger,
) {}
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): string
{
if ($data === '') {
throw new RuntimeException('Refusing to sign empty data');
}
try {
// The KMS performs the operation. The key never reaches this process.
return $this->kms->sign($this->keyId, $data, $algorithm);
} catch (\Throwable $error) {
// Fail closed. Do not log key material or signature bytes.
$this->logger->error('kms.sign.failed', ['key' => $this->keyId]);
throw new RuntimeException('KMS signing failed', previous: $error);
}
}
public function getCertificateDer(): string
{
return $this->kms->certificate($this->keyId);
}
/** @return array<string> */
public function getCertificateChainDer(): array
{
return $this->kms->chain($this->keyId);
}
public function getPublicKeyAlgorithm(): string
{
return $this->kms->algorithm($this->keyId);
}
}
  • Format byte tanda tangan. Kembalikan byte tanda tangan mentah. Untuk Rivest-Shamir-Adleman (RSA), byte tersebut adalah DER. Untuk Elliptic Curve Digital Signature Algorithm (ECDSA), byte tersebut adalah nilai r mentah diikuti oleh nilai s.
  • Urutan rantai. getCertificateChainDer() tidak menyertakan sertifikat penanda tangan. Urutkan sertifikat antara dari penerbit hingga root.
  • Identifier algoritma. sign() menggunakan identifier bergaya OpenSSL. getPublicKeyAlgorithm() mengembalikan nama algoritma X.509.
  • Kegagalan bersifat fail-closed. Lemparkan RuntimeException pada setiap kesalahan token atau KMS. Jangan mengembalikan tanda tangan parsial atau kosong.
  • Penghancuran kunci. Ketika sebuah kunci mencapai akhir cryptoperiod-nya, hancurkan kunci tersebut sesuai prosedur manajemen kunci Anda. NIST SP 800-57 Part 1 Revision 5 §8.2.1.2 menyatakan bahwa kunci harus dihancurkan segera setelah tidak lagi dibutuhkan. Penghancuran itu sendiri mengikuti §8.3.4.

Kontrak ini hanya mentransfer data yang akan ditandatangani dan material sertifikat. Kontrak ini tidak mentransfer konten dokumen atau data pribadi ke back end penandatanganan. Jaga agar rentang byte tetap minimal. Jangan menempatkan data pribadi pada bidang alasan atau lokasi penandatanganan. Bidang-bidang tersebut tetap dapat diamati di dalam berkas yang telah ditandatangani.

Jangan pernah mencatat data yang diteruskan ke sign(), byte tanda tangan yang dikembalikan, identifier kunci dalam bentuk yang dapat dipulihkan, atau komponen privat sertifikat apa pun. Catat hanya hasil operasi dan referensi yang tidak dapat dibalik. Hook SignatureAppliedEvent adalah jangkar audit yang didukung. Lihat Pemicu aksi.

AsetAncamanMitigasi
Private keyKeluar ke memori prosesKontrak mewajibkan penandatanganan di dalam batas; PKCS#11 CKA_SENSITIVE / CKA_EXTRACTABLE menegakkan sifat tidak dapat diekstraksi
Oracle penandatangananPermintaan penandatanganan tanpa batasImplementasi membatasi laju dan mengautentikasi pemanggil
Rantai sertifikatSubstitusiImplementasi mengembalikan rantai yang terbentuk hingga ke root tepercaya
Byte tanda tanganPengungkapan melalui logJalur kesalahan fail-closed; tidak ada material tanda tangan dalam telemetri
Kunci yang melewati cryptoperiodPenggunaan berkelanjutanPenghancuran kunci sesuai NIST SP 800-57 Part 1 Revision 5 §8.2.1.2

Level tanda tangan sesuai dengan profil PAdES. ETSI EN 319 142-2 §5.1 mendefinisikan profil PAdES yang diperluas di atas blok penyusun dasar EN 319 142-1. Engine merakit blok-blok penyusun tersebut dari material yang disediakan signer Anda. Manajemen kunci selaras dengan siklus hidup NIST SP 800-57 Part 1 Revision 5, termasuk persyaratan penghancuran §8.2.1.2. Penyimpanan kunci perangkat keras selaras dengan atribut kunci yang tidak dapat diekstraksi pada PKCS#11 v3.1. Sitasi dicatat di front matter halaman.

Halaman ini mencakup penyimpanan kunci PKCS#11 dan hardware security module (HSM), sehingga front matter-nya menetapkan export_control_class: legal-review-required. Berdasarkan kebijakan peninjauan dokumentasi (plan §17 gate 6), setiap halaman dengan mode keamanan, path, atau konten yang cocok dengan PAdES, FIPS, HSM, atau PKCS#11 memerlukan persetujuan dari tim GitHub @nextpdf-labs/crypto-reviewers sebelum dapat dipublikasikan. Persetujuan CODEOWNERS tersebut adalah gate merge wajib: halaman tetap publish: false sampai peninjauan kontrol ekspor legal dan peninjauan oleh @nextpdf-labs/crypto-reviewers sama-sama selesai.

NextPDF Enterprise menyediakan implementasi terdukung dari kontrak ini dengan penyimpanan berbasis key management system, perakitan rantai sertifikat, dan integrasi audit. Anda dapat mengimplementasikan HsmSignerInterface sendiri di Core atau menggunakan implementasi Enterprise melalui kontrak publik yang sama tanpa perubahan kode.

Glosarium mendefinisikan key management system, cryptoperiod, dan HSM; lihat glosarium yang dipublikasikan untuk setiap definisi kanonisnya.