如何在没有完整 X509 证书的情况下使用 PdfPkcs7?
How to use PdfPkcs7 without a full X509 certificate?
我们正在尝试通过移动签名服务在外部对 PDF 进行签名。 Whosebug 中有很多关于此主题的问题,尤其是来自土耳其的问题。参见:。这里完全一样。
我们要求 MSSP 提供个人资料信息。由于保护个人数据的法律,我们无法检索签名者的完整 public 证书或链。
配置文件查询服务响应:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ns1:MSS_ProfileQueryResponse xmlns:ns1="http://turkcelltech.com/mobilesignature/validation/soap">
<MSS_ProfileResp xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" xmlns:ns4="http://www.w3.org/2003/05/soap-envelope" xmlns:ns5="http://uri.etsi.org/TS102204/v1.1.2#" MajorVersion="1" MinorVersion="1">
<ns5:AP_Info AP_ID="http://localhost" AP_TransID="_1264751036088" AP_PWD="secret" Instant="2013-06-12T04:54:43.260Z"/>
<ns5:MSSP_Info Instant="2020-07-22T18:43:33.723+03:00">
<ns5:MSSP_ID/>
</ns5:MSSP_Info>
<ns5:SignatureProfile>
<ns5:mssURI>http://uri.turkcellteknoloji.com.tr/MobileSignature/profile2</ns5:mssURI>
<ns5:CertIssuerDN>C=TR,O=Elektronik Bilgi Guvenligi A.S.,CN=Turkcell Mobil NES Hizmet Saglayicisi S2</ns5:CertIssuerDN>
<ns5:CertSerialNumber>313460597714010174158784514408553193353</ns5:CertSerialNumber>
<ns5:CertHash>
<ns5:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ns5:DigestValue>MVI4FeeToX6TDPLh3h9zEw19ulzTomxPB/zDvnyWzKA=</ns5:DigestValue>
</ns5:CertHash>
<ns5:msspUrl>http://localhost</ns5:msspUrl>
<ns5:certIssuerDN-DER>MGoxCzAJBgNVBAYTAlRSMSgwJgYDVQQKDB9FbGVrdHJvbmlrIEJpbGdpIEd1dmVubGlnaSBBLlMuMTEwLwYDVQQDDChUdXJrY2VsbCBNb2JpbCBORVMgSGl6bWV0IFNhZ2xheWljaXNpIFMy</ns5:certIssuerDN-DER>
</ns5:SignatureProfile>
<ns5:Status>
<ns5:StatusCode Value="100"/>
<ns5:StatusMessage>REQUEST_OK</ns5:StatusMessage>
</ns5:Status>
</MSS_ProfileResp>
</ns1:MSS_ProfileQueryResponse>
</soap:Body>
</soap:Envelope>
我们仍然可以使用此信息创建 SigningCertificateV2 实例。
var certAlgorithmIdentifier = new AlgorithmIdentifier(certHashDigestAlgorithm);
var certHash = Convert.FromBase64String(certHashDigestValue);
var issuer = new GeneralNames(new GeneralName(new X509Name(certIssuerDN)));
var serial = new DerInteger(new BigInteger(certSerialNumber));
var issuerSerial = new IssuerSerial(issuer, serial);
var certIDv2 = new EssCertIDv2(certAlgorithmIdentifier, certHash, issuerSerial);
return new SigningCertificateV2(certIDv2);
ASN.1 结果是:
SEQUENCE (1 elem)
SEQUENCE (1 elem)
SEQUENCE (3 elem)
SEQUENCE (1 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.11 sha256WithRSAEncryption (PKCS #1)
OCTET STRING (32 byte) 31523815E793A17E930CF2E1DE1F73130D7DBA5CD3A26C4F07FCC3BE7C96CCA0
SEQUENCE (2 elem)
SEQUENCE (1 elem)
[4] (1 elem)
SEQUENCE (3 elem)
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component)
PrintableString TR
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component)
UTF8String Elektronik Bilgi Guvenligi A.S.
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
UTF8String Turkcell Mobil NES Hizmet Saglayicisi S2
INTEGER (128 bit) 313460597714010174158784514408553193353
我们还可以从 CA 的钥匙串中检索根证书和中间证书。
- https://www.e-guven.com/media/2582/eguvenkoks2.crt
- https://www.e-guven.com/media/2584/turkcellmobilimzaaltkoks2.crt
那么,我们如何将它们结合起来与 PdfSigner 和 PdfPKCS7 一起使用来签署 PDF?我们应该在外部创建 CMSSignedData 吗?如何创建?这个路线图正确吗?
- 根据 ByteRange 的 PDF 内容计算摘要。
- 在外部创建一个 Cms 容器。 (不知何故)
- 添加签名者信息,并将内容摘要放入容器。
- 根据 CMS 认证属性计算摘要。
- 通过 MSSP 签署最终摘要,并检索 XMLDSig。
- 向现有 CMS 容器添加签名字段。
- 用 DER 编码的 CmsSignedData 在 PDF 签名字典中填充 /Contents。
我知道有很多关于同一主题的问题。但是其中 none 足够清楚地解释处理签名证书的过程。
编辑:
澄清一下,当我们发送 SHA-256 摘要(base64 编码)时,我们将在签名请求后检索 X509 证书。
XML签名,签名服务返回:
<?xml version="1.0" encoding="UTF-8" ?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm=""/>
<SignatureMethod Algorithm=""/>
<Reference>
<DigestMethod Algorithm=""/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue>
...
</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>
...
</Modulus>
<Exponent>
...
</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509Certificate>
...
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
但是正如我之前提到的,我们无法在签名请求之前检索签名者的完整 public 证书。只有证书哈希、序列号和颁发者 DN。此信息足以在签署请求之前设置 ESS signing-certificate-v2
属性。
https://www.rfc-editor.org/rfc/rfc5126#section-5.7.3
这就是为什么,我们应该能够在本地创建 CmsSignedData,并添加 pdf 内容摘要、签名者信息(从配置文件查询中检索到的签名证书 v2)并从此 CmsSignedData 实例获取最终摘要,以进行签名MSSP 签名服务。之后,当我们从服务中检索 XML 签名时,我们可以在这个 CmsSignedData 实例中填充其他未签名的属性、证书。
回答问题的第一个版本,给人的印象是完整的签名者证书根本不可用,甚至在签名服务中也不可用答案:
如果不嵌入签名者的 X509 证书,则无法创建 pdf 签名。
至少不是以可互操作的方式。
根据pdf规范:
12.8.3.2 PKCS #1 signatures
[...] For signing PDF files using PKCS #1, the only value of SubFilter that should be used is adbe.x509.rsa_sha1.
[...] The certificate chain of the signer shall be stored in the Cert entry.
和
12.8.3.3 CMS (PKCS #7) signatures
[...] SubFilter shall take one of the following values:
- adbe.pkcs7.detached [...]
- adbe.pkcs7.sha1 [...]
At minimum the CMS object shall include the signer’s X.509 signing certificate. This certificate shall be used to verify the signature value in Contents.
(ISO 32000-2,第 12.8.3 节签名互操作性)
如果您正在研究 PAdES 签名,根据 PAdES 规范:
6.3 PAdES baseline signatures
[...]
Additional requirements:
a) The generator shall include the signing certificate in the SignedData.certificates field.
(ETSI EN 319 142-1 V1.1.1)
因此,如果没有签名者的 X509 证书,您将无法创建可互操作的 pdf 签名。
我们正在尝试通过移动签名服务在外部对 PDF 进行签名。 Whosebug 中有很多关于此主题的问题,尤其是来自土耳其的问题。参见:
我们要求 MSSP 提供个人资料信息。由于保护个人数据的法律,我们无法检索签名者的完整 public 证书或链。
配置文件查询服务响应:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ns1:MSS_ProfileQueryResponse xmlns:ns1="http://turkcelltech.com/mobilesignature/validation/soap">
<MSS_ProfileResp xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" xmlns:ns4="http://www.w3.org/2003/05/soap-envelope" xmlns:ns5="http://uri.etsi.org/TS102204/v1.1.2#" MajorVersion="1" MinorVersion="1">
<ns5:AP_Info AP_ID="http://localhost" AP_TransID="_1264751036088" AP_PWD="secret" Instant="2013-06-12T04:54:43.260Z"/>
<ns5:MSSP_Info Instant="2020-07-22T18:43:33.723+03:00">
<ns5:MSSP_ID/>
</ns5:MSSP_Info>
<ns5:SignatureProfile>
<ns5:mssURI>http://uri.turkcellteknoloji.com.tr/MobileSignature/profile2</ns5:mssURI>
<ns5:CertIssuerDN>C=TR,O=Elektronik Bilgi Guvenligi A.S.,CN=Turkcell Mobil NES Hizmet Saglayicisi S2</ns5:CertIssuerDN>
<ns5:CertSerialNumber>313460597714010174158784514408553193353</ns5:CertSerialNumber>
<ns5:CertHash>
<ns5:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ns5:DigestValue>MVI4FeeToX6TDPLh3h9zEw19ulzTomxPB/zDvnyWzKA=</ns5:DigestValue>
</ns5:CertHash>
<ns5:msspUrl>http://localhost</ns5:msspUrl>
<ns5:certIssuerDN-DER>MGoxCzAJBgNVBAYTAlRSMSgwJgYDVQQKDB9FbGVrdHJvbmlrIEJpbGdpIEd1dmVubGlnaSBBLlMuMTEwLwYDVQQDDChUdXJrY2VsbCBNb2JpbCBORVMgSGl6bWV0IFNhZ2xheWljaXNpIFMy</ns5:certIssuerDN-DER>
</ns5:SignatureProfile>
<ns5:Status>
<ns5:StatusCode Value="100"/>
<ns5:StatusMessage>REQUEST_OK</ns5:StatusMessage>
</ns5:Status>
</MSS_ProfileResp>
</ns1:MSS_ProfileQueryResponse>
</soap:Body>
</soap:Envelope>
我们仍然可以使用此信息创建 SigningCertificateV2 实例。
var certAlgorithmIdentifier = new AlgorithmIdentifier(certHashDigestAlgorithm);
var certHash = Convert.FromBase64String(certHashDigestValue);
var issuer = new GeneralNames(new GeneralName(new X509Name(certIssuerDN)));
var serial = new DerInteger(new BigInteger(certSerialNumber));
var issuerSerial = new IssuerSerial(issuer, serial);
var certIDv2 = new EssCertIDv2(certAlgorithmIdentifier, certHash, issuerSerial);
return new SigningCertificateV2(certIDv2);
ASN.1 结果是:
SEQUENCE (1 elem)
SEQUENCE (1 elem)
SEQUENCE (3 elem)
SEQUENCE (1 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.11 sha256WithRSAEncryption (PKCS #1)
OCTET STRING (32 byte) 31523815E793A17E930CF2E1DE1F73130D7DBA5CD3A26C4F07FCC3BE7C96CCA0
SEQUENCE (2 elem)
SEQUENCE (1 elem)
[4] (1 elem)
SEQUENCE (3 elem)
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component)
PrintableString TR
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component)
UTF8String Elektronik Bilgi Guvenligi A.S.
SET (1 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
UTF8String Turkcell Mobil NES Hizmet Saglayicisi S2
INTEGER (128 bit) 313460597714010174158784514408553193353
我们还可以从 CA 的钥匙串中检索根证书和中间证书。
- https://www.e-guven.com/media/2582/eguvenkoks2.crt
- https://www.e-guven.com/media/2584/turkcellmobilimzaaltkoks2.crt
那么,我们如何将它们结合起来与 PdfSigner 和 PdfPKCS7 一起使用来签署 PDF?我们应该在外部创建 CMSSignedData 吗?如何创建?这个路线图正确吗?
- 根据 ByteRange 的 PDF 内容计算摘要。
- 在外部创建一个 Cms 容器。 (不知何故)
- 添加签名者信息,并将内容摘要放入容器。
- 根据 CMS 认证属性计算摘要。
- 通过 MSSP 签署最终摘要,并检索 XMLDSig。
- 向现有 CMS 容器添加签名字段。
- 用 DER 编码的 CmsSignedData 在 PDF 签名字典中填充 /Contents。
我知道有很多关于同一主题的问题。但是其中 none 足够清楚地解释处理签名证书的过程。
编辑:
澄清一下,当我们发送 SHA-256 摘要(base64 编码)时,我们将在签名请求后检索 X509 证书。
XML签名,签名服务返回:
<?xml version="1.0" encoding="UTF-8" ?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm=""/>
<SignatureMethod Algorithm=""/>
<Reference>
<DigestMethod Algorithm=""/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue>
...
</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>
...
</Modulus>
<Exponent>
...
</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509Certificate>
...
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
但是正如我之前提到的,我们无法在签名请求之前检索签名者的完整 public 证书。只有证书哈希、序列号和颁发者 DN。此信息足以在签署请求之前设置 ESS signing-certificate-v2
属性。
https://www.rfc-editor.org/rfc/rfc5126#section-5.7.3
这就是为什么,我们应该能够在本地创建 CmsSignedData,并添加 pdf 内容摘要、签名者信息(从配置文件查询中检索到的签名证书 v2)并从此 CmsSignedData 实例获取最终摘要,以进行签名MSSP 签名服务。之后,当我们从服务中检索 XML 签名时,我们可以在这个 CmsSignedData 实例中填充其他未签名的属性、证书。
回答问题的第一个版本,给人的印象是完整的签名者证书根本不可用,甚至在签名服务中也不可用答案:
如果不嵌入签名者的 X509 证书,则无法创建 pdf 签名。
至少不是以可互操作的方式。
根据pdf规范:
12.8.3.2 PKCS #1 signatures
[...] For signing PDF files using PKCS #1, the only value of SubFilter that should be used is adbe.x509.rsa_sha1. [...] The certificate chain of the signer shall be stored in the Cert entry.
和
12.8.3.3 CMS (PKCS #7) signatures
[...] SubFilter shall take one of the following values:
- adbe.pkcs7.detached [...]
- adbe.pkcs7.sha1 [...]
At minimum the CMS object shall include the signer’s X.509 signing certificate. This certificate shall be used to verify the signature value in Contents.
(ISO 32000-2,第 12.8.3 节签名互操作性)
如果您正在研究 PAdES 签名,根据 PAdES 规范:
6.3 PAdES baseline signatures
[...]
Additional requirements:
a) The generator shall include the signing certificate in the SignedData.certificates field.
(ETSI EN 319 142-1 V1.1.1)
因此,如果没有签名者的 X509 证书,您将无法创建可互操作的 pdf 签名。