Pro الإصدار
التوقيع عبر Cloud KMS — مرجع متعمّق
نظرة سريعة
قسم بعنوان «نظرة سريعة»تُمثّل هذه الصفحة المرجع على مستوى العقد لواجهة التوقيع عبر cloud-KMS في NextPDF Pro. تتكوّن هذه الواجهة من واجهة موفّر خدمة واحدة، NextPDF\Pro\Security\Signing\Kms\KmsSignerInterface، وثلاثة موقّعات لموفّري الخدمة: AwsKmsSigner وAzureKeyVaultSigner وGcpKmsSigner. ويربط محوّلان اثنان، AwsKmsSigningStrategy وAzureKeyVaultSigningStrategy، الموقّع بعقد SigningStrategy في Pro. ويُرسل كل موقّع ملخّص رسالة فقط إلى موفّر خدمته عبر PSR-18 HTTP. ولا يعبر المفتاح الخاص ولا المستند هذا الحد أبدًا. وتُوضّح هذه الصفحة واجهة API العامة، وعقد السلوك القابل للملاحظة، وأنماط الإخفاق المُصنّفة. أما تنظيم الجلسات (RemoteSigningSession، SequentialSigner) والختم الزمني (PadesBtTimestamper) فموجودان في صفحاتهما الخاصة.
التوفّر والترخيص
قسم بعنوان «التوفّر والترخيص»تُشحن هذه القدرة ضمن NextPDF Pro (nextpdf/pro) وتُفعَّل بحزمة ترخيص من فئة Pro. ولا يُحمّل أي نشر لا يملك ذلك الاستحقاق أصنافَ القدرة. قارن الإصدارات واحصل على ترخيص.
واجهة API العامة
قسم بعنوان «واجهة API العامة»| الرمز | المعاملات | السلوك الافتراضي | القيمة المُعادة | يرمي أو يُخفق بـ | ملاحظات |
|---|---|---|---|---|---|
KmsSignerInterface | — | يُوسّع عقد HsmSignerInterface في Core | — | — | واجهة SPI لمُشغّلات KMS وHSM؛ المعرّفات المدمجة المحجوزة: aws-kms، azure-keyvault، gcp-kms، pkcs11، openssl-cli |
KmsSignerInterface::providerId() | لا شيء | مفتاح بحث ثابت في السجلّ | non-empty-string | — | يجب على مُشغّلات الأطراف الخارجية وضع مُعرّفها في مساحة اسم خاصة |
KmsSignerInterface::signWithVersion() | $data, $algorithm = 'sha256WithRSAEncryption', $keyVersion = null | يعود إصدار المفتاح null إلى الإعداد الافتراضي لموفّر الخدمة | string ثمانيّات التوقيع: RSA كما يُعيدها موفّر الخدمة (تُوضع مباشرةً في SignerInfo.signature)، وECDSA بصيغة DER ECDSA-Sig-Value وفق قواعد CMS | KeyManagementException, UnsupportedAlgorithmException, SignatureFailedException | تختلف دلالات null حسب موفّر الخدمة؛ راجع عقد السلوك |
KmsSignerInterface::supportsAlgorithm() | string $algorithm | فحص قدرة؛ لا يُجري أي عمليات I/O | bool | — | يُستدعى قبل اختيار موفّر الخدمة |
KmsSignerInterface::supportedAlgorithms() | لا شيء | يُدرج الأسماء بنمط OpenSSL التي يقبلها موفّر الخدمة | list<non-empty-string> | — | — |
AwsKmsSigner | الباني: AwsKmsConfig، شهادة DER، سلسلة DER، عميل PSR-18، مصانع PSR-17، مُسجّل PSR-3 | الخوارزمية الافتراضية هي KmsSigningAlgorithm::RsaPkcs1Sha256 | — | راجع التوابع | final؛ PROVIDER_ID = 'aws-kms' |
AwsKmsSigner::create() | مُعرّف المفتاح، شهادة DER، تبعيّات PSR، سلسلة اختيارية، إعداد، مُسجّل | يبني AwsKmsConfig::fromEnvironment($keyId) عندما يكون $config يساوي null | self | — | يقرأ متغيّرات البيئة القياسية AWS_* |
AwsKmsSigner::withAlgorithm() | KmsSigningAlgorithm $algorithm | يُعيد نسخة معدّلة | self | — | يجب أن يطابق نوع المفتاح المُهيّأ في AWS KMS |
AwsKmsSigner::sign() | $data, $algorithm = 'sha256WithRSAEncryption' | يُفوّض إلى signWithVersion($data, $algorithm, null) | string | كما في signWithVersion() | مسار عقد Core القديم ثنائي الوسائط |
AzureKeyVaultSigner | الباني: AzureKeyVaultConfig، شهادة DER، سلسلة DER، عميل PSR-18، مصانع PSR-17، مُسجّل PSR-3 | الخوارزمية الافتراضية هي AzureSigningAlgorithm::Rs256؛ ورمز وصول في الإعداد يُمهّد رمز الحامل bearer | — | راجع التوابع | final؛ PROVIDER_ID = 'azure-keyvault' |
AzureKeyVaultSigner::create() | اسم الخزنة، اسم المفتاح، شهادة DER، تبعيّات PSR، سلسلة اختيارية، إعداد، مُسجّل | يبني AzureKeyVaultConfig::fromEnvironment() عندما يكون $config يساوي null | self | — | يدعم رمزًا مُحصّلًا مسبقًا أو بيانات اعتماد كيان الخدمة (service-principal) |
AzureKeyVaultSigner::withAlgorithm() | AzureSigningAlgorithm $algorithm | يُعيد نسخة معدّلة | self | — | مفاتيح RSA تستخدم قيم RS/PS؛ ومفاتيح EC تستخدم قيم ES |
GcpKmsSigner | الباني: GcpKmsConfig، شهادة DER، سلسلة DER، عميل PSR-18، مصانع PSR-17، مُسجّل PSR-3 | الخوارزمية الافتراضية هي GcpKmsSigningAlgorithm::RsaSignPkcs1_2048Sha256 | — | راجع التوابع | final؛ PROVIDER_ID = 'gcp-kms'، API_VERSION = 'v1' |
GcpKmsSigner::create() | مُعرّف المشروع، الموقع، حلقة المفاتيح، مفتاح التعمية، شهادة DER، تبعيّات PSR، سلسلة اختيارية، إعداد، مُسجّل | يبني GcpKmsConfig::fromEnvironment() عندما يكون $config يساوي null | self | — | يُفوَّض الحصول على رمز الحامل إلى المُستدعي |
GcpKmsSigner::withAlgorithm() | GcpKmsSigningAlgorithm $algorithm | معاينة وقت الإعداد فقط؛ واسم السلك لكل استدعاء هو الحاسم وقت التوقيع | self | — | حجم المفتاح مُثبَّت بواسطة CryptoKeyVersion المُهيّأ |
AwsKmsSigningStrategy | الباني: AwsKmsSigner $signer | متزامن؛ isAsync() يُعيد false | — | يُمرّر استثناءات الموقّع المُغلَّف | محوّل لـ RemoteSigningSession::complete() |
AzureKeyVaultSigningStrategy | الباني: AzureKeyVaultSigner $signer | متزامن؛ isAsync() يُعيد false | — | يُمرّر استثناءات الموقّع المُغلَّف | محوّل لـ RemoteSigningSession::complete() |
KmsSigningAlgorithm | تعداد، 9 حالات (RSA PKCS#1، RSA-PSS، ECDSA؛ SHA-256/384/512) | — | قيم سلك SigningAlgorithm في AWS KMS | InvalidArgumentException من fromOpenSslName() | resolveForWireName() يحافظ على ملخّص PSS المُهيّأ |
AzureSigningAlgorithm | تعداد، 9 حالات (RS256…ES512) | — | قيم بنمط JWA في Azure Key Vault | InvalidArgumentException من fromOpenSslName() | isEcdsa() يُعلّم القيم التي يحتاج ناتجها تحويلًا إلى DER |
GcpKmsSigningAlgorithm | تعداد، 10 حالات (EC P-256/P-384، RSA PKCS#1، RSA-PSS) | — | قيم خوارزمية CryptoKeyVersion في GCP | UnsupportedAlgorithmException من fromOpenSslName() | يختار تحليل اسم السلك أصغر حجم مفتاح مطابق |
توقيعات نقاط الدخول
قسم بعنوان «توقيعات نقاط الدخول»public function providerId(): string;
public function signWithVersion( string $data, string $algorithm = 'sha256WithRSAEncryption', ?string $keyVersion = null,): string;
public function supportsAlgorithm(string $algorithm): bool;
public function supportedAlgorithms(): array;public static function create( string $keyId, string $certDer, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, array $chainDer = [], ?AwsKmsConfig $config = null, ?LoggerInterface $logger = null,): self
public function withAlgorithm(KmsSigningAlgorithm $algorithm): self
public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): stringpublic static function create( string $vaultName, string $keyName, string $certDer, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, array $chainDer = [], ?AzureKeyVaultConfig $config = null, ?LoggerInterface $logger = null,): self
public function withAlgorithm(AzureSigningAlgorithm $algorithm): selfpublic static function create( string $projectId, string $location, string $keyRing, string $cryptoKey, string $certDer, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, array $chainDer = [], ?GcpKmsConfig $config = null, ?LoggerInterface $logger = null,): self
public function withAlgorithm(GcpKmsSigningAlgorithm $algorithm): selfpublic function __construct( private AwsKmsSigner $signer,) {}
public function sign(string $signedAttributesDer): stringpublic function __construct( private AzureKeyVaultSigner $signer,) {}
public function sign(string $signedAttributesDer): stringعقد السلوك
قسم بعنوان «عقد السلوك»تحليل العقد
قسم بعنوان «تحليل العقد»يُوسّع KmsSignerInterface عقد HsmSignerInterface في Core. ويُضيف providerId()، وsignWithVersion() المُدرك لإصدار المفتاح، وفحصَي القدرة supportsAlgorithm() وsupportedAlgorithms(). ويُفوّض التابع الموروث sign() ثنائي الوسائط إلى signWithVersion() بإصدار مفتاح null في الموقّعات الثلاثة جميعها. وتُنفَّذ getCertificateDer() وgetCertificateChainDer() وgetPublicKeyAlgorithm() من المواد المُزوَّدة عبر الباني. ولا تُجري فحوص القدرة أي عمليات I/O. ويُتيح كل موقّع أيضًا مُوصِّلَي getSigningAlgorithm() وgetConfig() لأغراض الفحص.
إرسال الملخّص فقط
قسم بعنوان «إرسال الملخّص فقط»يحسب كل موقّع ملخّص $data محليًا وفق ملخّص الخوارزمية المُحلَّلة، ويُرسل ذلك الملخّص فقط. يتلقّى AWS ملخّصًا بترميز base64 مع MessageType: DIGEST. ويتلقّى Azure ملخّصًا بترميز base64url في جسم طلب التوقيع. ويتلقّى GCP ملخّصًا بترميز base64 في حقل الملخّص الخاص بالخوارزمية. ولا تظهر بايتات المستند أبدًا في طلب موفّر الخدمة. ويستخدم كل النقل عميل PSR-18 HTTP قياسيًا عبر نقطة نهاية HTTPS الخاصة بموفّر الخدمة؛ ولا تتدخّل أي SDK من مورّد سحابي.
تحليل إصدار المفتاح
قسم بعنوان «تحليل إصدار المفتاح»يتحقّق signWithVersion() من وسيط إصدار المفتاح بأسلوب الإخفاق المُغلَق (fail-closed) قبل بناء أي طلب. وأي قيمة تُخالف قواعد موفّر الخدمة تُطلق KeyManagementException وتمنع حَقن مقطع URL أو KeyId.
| موفّر الخدمة | إصدار المفتاح null | السلسلة الفارغة | قواعد التجاوز |
|---|---|---|---|
AwsKmsSigner | يستخدم AwsKmsConfig::$keyId؛ ويُحلَّل الاسم المستعار (alias) أو ARN إلى المفتاح الحالي في جانب موفّر الخدمة | مرفوضة | UUID (بشُرَط أو بدونها)، أو alias/<name>، أو ARN لمفتاح/اسم مستعار في KMS |
AzureKeyVaultSigner | يستخدم إصدار المفتاح المُهيّأ؛ وقيمة إعداد فارغة تختار أحدث إصدار مُفعّل على جانب الخادم | مرفوضة | مُعرّف ست عشري من 32 حرفًا |
GcpKmsSigner | يستخدم الإصدار المُثبَّت في GcpKmsConfig؛ وإن لم يُثبَّت أي إصدار، يُطلق KeyManagementException | مرفوضة | مُعرّف CryptoKeyVersion عشري، أرقام فقط |
لا يملك GCP بُنية أوّلية لـ ”الإصدار النشط“ على جانب الخادم. وتعمل نقطة نهاية التوقيع غير المتماثل على مورد cryptoKeyVersions/{n} محدّد فقط، لذا يجب أن يكون الإصدار قابلًا للتحليل دائمًا.
تحليل الخوارزمية
قسم بعنوان «تحليل الخوارزمية»تُمرّر طبقة الاستراتيجية اسم سلك بنمط OpenSSL. ويقبل AWS وAzure سبعة أسماء سلك (PKCS#1 وECDSA عند SHA-256/384/512، إضافةً إلى RSASSA-PSS). ويقبل GCP خمسة (sha256WithRSAEncryption، sha512WithRSAEncryption، RSASSA-PSS، ecdsa-with-SHA256، ecdsa-with-SHA384). ولا يُرمّز اسم السلك RSASSA-PSS أي ملخّص، لذا فهو غامض من حيث الملخّص. ويُحلّله AwsKmsSigner عبر KmsSigningAlgorithm::resolveForWireName()، الذي يحافظ على ملخّص متغيّر PSS المُهيّأ. ويثق AzureKeyVaultSigner بمتغيّر PSS المُهيّأ للاسم الغامض. ويُطلق UnsupportedAlgorithmException إذا كان ملخّص PSS المُحلَّل سيختلف عن المُهيّأ. ويُعيد GcpKmsSigner تحليل التعداد من اسم السلك في كل استدعاء؛ وwithAlgorithm() في GCP معاينة وقت إعداد ولا يُغيّر سلوك وقت التوقيع. وأي اسم سلك غير مدعوم يُطلق UnsupportedAlgorithmException قبل أي استدعاء شبكي. وفي AwsKmsSigner وGcpKmsSigner، يُحدّث استدعاء التوقيع القيمة التي يُبلّغ عنها getSigningAlgorithm() لاحقًا إلى الخوارزمية المُحلَّلة لكل استدعاء. وفي AzureKeyVaultSigner، يكون التحليل محليًا للاستدعاء وتبقى القيمة المُهيّأة هي المرجعية.
تسوية التوقيع
قسم بعنوان «تسوية التوقيع»يُعيد AWS وGCP التواقيع بالصيغة التي يستهلكها CMS: تدخل ثمانيّات توقيع RSA إلى SignerInfo.signature دون تغيير، ويصل ECDSA مُرمَّزًا بـ DER. ويُعيد Azure توقيع ECDSA بصيغة IEEE P1363 الخام (r||s)، والتي يُحوّلها الموقّع إلى ECDSA-Sig-Value بترميز DER قبل الإعادة.
تكامل CMS والتجاور
قسم بعنوان «تكامل CMS والتجاور»يُوقّع محوّل SigningStrategy السمات المُوقَّعة المُرمَّزة بـ DER التي تُزوّدها الجلسة. ومع وجود السمات المُوقَّعة، يكون دخل توقيع CMS هو ملخّص ترميز DER الكامل لقيمة SignedAttrs — RFC 5652 §5.4. ويُغذّي getSignatureAlgorithmOid() وgetDigestAlgorithm() في المحوّل حقلَي signatureAlgorithm وdigestAlgorithm في SignerInfo — RFC 5652 §5.3. وتصبح البايتات المُعادة سلسلة OCTET STRING لتوقيع SignerInfo — RFC 5652 §5.5. ويخصّ تجميع CMS ومعالجة ByteRange ودورة حياة الجلسة RemoteSigningSession؛ وتخصّ التدفّقات متعدّدة الأطراف SequentialSigner. ويُطبّق PadesBtTimestamper — لا هذه الموقّعات — خَتمًا زمنيًا لتوقيع PAdES B-T، حيث يحسب messageImprint فيه بصمة قيمة توقيع SignerInfo — RFC 3161 Appendix A. والثلاثة جميعها مُوثَّقة في المرجع الأمني المتعمّق لـ Pro.
الحالات الحدّية وأنماط الإخفاق
قسم بعنوان «الحالات الحدّية وأنماط الإخفاق»- يُرفض إصدار المفتاح بسلسلة فارغة في موفّري الخدمة الثلاثة جميعهم. مرّر
null لوراثة الإعداد الافتراضي المُهيّأ. - يُرفض أي إصدار مفتاح مُشوَّه قبل بناء أي طلب، مع تسمية القيمة المُخالِفة في الاستثناء.
- يُطلق
AwsKmsSigner استثناء KeyManagementException عند AwsKmsConfig::$keyId فارغ وإصدار مفتاح null. - تُقابَل استجابات موفّر الخدمة التي تُشير إلى إخفاق في إدارة المفاتيح بـ
KeyManagementException: في AWS NotFoundException أو DisabledException أو KeyUnavailableException أو InvalidKeyUsageException أو HTTP 404؛ وفي Azure HTTP 404 أو KeyNotFound أو KeyDisabled أو KeyNotActive؛ وفي GCP HTTP 404 أو 409 أو NOT_FOUND أو FAILED_PRECONDITION أو HTTP 400 تُسمّي رسالتها إصدارًا. - استجابات موفّر الخدمة الأخرى غير 200 تُطلق
SignatureFailedException في AWS وGCP، وAzureKeyVaultException في Azure. - يُقابَل أي إخفاق نقل PSR-18 أثناء التوقيع بـ
SignatureFailedException مع الحفاظ على استثناء العميل كسبب سابق (previous throwable). - يُطلق
AzureKeyVaultSigner استثناء AzureKeyVaultException عند غياب رمز الوصول وبيانات اعتماد كيان الخدمة قبل أي استدعاء للخزنة. كما يُطلق الحصول الفاشل على رمز Azure AD استثناء AzureKeyVaultException. - يتحقّق
AzureKeyVaultSigner من اسم الخزنة واسم المفتاح وإصدار المفتاح ومُعرّف المستأجر مقابل قواعد Azure المنشورة عند نقطة اختناق الطلب. وأي قيمة تحمل محارف بنيوية لعنوان URL تُخفق بأسلوب مُغلَق مع AzureKeyVaultException. - يُطلق
GcpKmsSigner استثناء SignatureFailedException عند غياب رمز حامل OAuth2؛ والحصول على الرمز مسؤولية المُستدعي. - أي استجابة من موفّر الخدمة ليست JSON صالحًا، أو تفتقر إلى حقل التوقيع، تُطلق
SignatureFailedException (في Azure: حقل value مفقود يُطلق AzureKeyVaultException). - حقل توقيع من موفّر الخدمة يُخفق في فك ترميز base64 يُطلق
SignatureFailedException في AWS وGCP، وAzureKeyVaultException في Azure. - لا يُشحن أي محوّل
SigningStrategy لـ GcpKmsSigner في 3.1.0. ويُستهلك موقّع GCP عبر عقد KmsSignerInterface مباشرةً.
سلوك وضع FIPS
قسم بعنوان «سلوك وضع FIPS»يُوجّه AwsKmsConfig::withFipsEndpoint() الطلبات إلى نقطة نهاية kms-fips الخاصة بالمنطقة. وحالة اعتماد FIPS لتلك النقطة هي خاصية لـ AWS، لا لـ NextPDF. ولا يُتيح AzureKeyVaultConfig وGcpKmsConfig أي مُساعد مخصّص لنقطة نهاية FIPS في 3.1.0. ويجري حساب الملخّص داخل العملية بدالة PHP hash() وليس هو نفسه وحدة معتمَدة. ويمكن لـ NextPDF Pro العمل مقابل حد KMS أو HSM معتمَد وفق FIPS، لكن NextPDF ليس وحدة تعمية معتمَدة وفق FIPS ولا يطرح أي ادّعاء باعتماد FIPS.
المطابقة
قسم بعنوان «المطابقة»| الادّعاء | المعيار | البند |
|---|---|---|
| يُوقّع الاستراتيجية السمات المُوقَّعة المُرمَّزة بـ DER؛ ويُغطّي ملخّص دخل توقيع CMS ترميز DER الكامل لـ SignedAttrs. | RFC 5652 | §5.4 |
| SignedAttributes مُرمَّزة بـ DER وتحمل content-type وmessage-digest كحد أدنى؛ ويُحدّد signatureAlgorithm خوارزمية الموقّع. | RFC 5652 | §5.3 |
| البايتات المُعادة للتوقيع مُرمَّزة كسلسلة OCTET STRING ومحمولة في حقل توقيع SignerInfo. | RFC 5652 | §5.5 |
| messageImprint الخاص بختم زمني للتوقيع يحسب بصمة قيمة توقيع SignerInfo (سطح B-T مُجاور، لا هذه الموقّعات). | RFC 3161 | Appendix A |
جميع البنود مُعاد صياغتها؛ ولا يُعيد NextPDF إنتاج النص المعياري. وهذه بيانات قدرة، لا شهادات اعتماد. ولا يحمل NextPDF أي شهادة اعتماد ولا يمنح أيًّا منها. أما هل يتحقّق توقيع مُنتَج أم لا فهو قرار المُتحقِّق مقابل مراسي الثقة والسياسة الخاصة به؛ والموقّعات تُعيد بايتات التوقيع ولا تؤكّد أي نتيجة موثوقة. وحِفظ المفتاح، وحماية المفتاح، والتحقّق من الخوارزمية في جانب موفّر الخدمة، هي خصائص لـ KMS المُهيّأ، لا لـ NextPDF.
ملاحظات التطوير
قسم بعنوان «ملاحظات التطوير»- التوفّر ضمن حزمة Pro:
AwsKmsSigner منذ 1.9.0، وAzureKeyVaultSigner منذ 2.0.0، وGcpKmsSigner وKmsSignerInterface منذ 2.1.0. وجميعها حاليّ في nextpdf/pro 3.1.0. - تعتمد الموقّعات على PSR-18 وPSR-17 وPSR-3 فقط. ولا تُطلب أو تُحزَّم أي SDK من AWS أو Azure أو Google.
- افحص
supportsAlgorithm() قبل التوقيع حتى يُرفض موفّر الخدمة غير المتوافق وقت الاختيار، لا في منتصف الجلسة. - تُحقَن حقول بيانات الاعتماد عبر الباني وتُعلَّم كمعاملات حسّاسة. وتحمل رسائل السجلّ حقولًا بنيوية فقط؛ ولا يُكتب أي بيان اعتماد أو رمز أو محتوى مستند في السجلّات.
- ثبّت إصدارات المفاتيح صراحةً في عمليات النشر الخاضعة للتنظيم. فالإعدادات الافتراضية لتحليل الاسم المستعار (في AWS) وأحدث إصدار مُفعّل (في Azure) مريحة لكنها ليست حتمية عبر عمليات التدوير.
- تُنفّذ مُشغّلات الأطراف الخارجية
KmsSignerInterface ويجب أن تضع providerId() الخاص بها في مساحة اسم لتجنّب التصادم مع المعرّفات المدمجة المحجوزة.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- التوقيع عبر Cloud KMS (القدرة) — صفحة الإرشادات: الإعداد، والتهيئة، وحد حِفظ المفتاح.
- الأمن — مرجع متعمّق —
RemoteSigningSession، وSequentialSigner، وسطح PAdES B-B/B-T، وعقد SigningStrategy. - التوقيع — مرجع متعمّق (Enterprise) — حد المُنتِج طويل الأمد B-LT/B-LTA.
- الأمن / التوقيع (Core) — موقّع CMS الأساسي (Core) والعقود التي تُوسّعها هذه الواجهة.
حدّ النشر
قسم بعنوان «حدّ النشر»تُوثّق هذه الصفحة السلوك القابل للملاحظة خارجيًا وواجهة API العامة المدعومة فقط. أما مسارات مساحات الأسماء الداخلية، والأصناف المساعدة، وجداول الآليات، وأسماء ملفات أدلة التشغيل، وبادئات التذاكر فهي خارج النطاق.