在签名中添加 LTV 使 pdf 使用 C# 无效
Adding LTV in signature makes pdf invalid using C#
将 LTV 添加到数字签名后,它显示文档已更改。
从这个问题中获取参考后:After LTV Certification Signature, PDF shows "Document has been Changed"
我对我的代码进行了更改,它适用于所有文档,但对于此文档:https://www.sendspace.com/file/3ulwn7 - 它显示无效签名。
我们也在使用来自 global sign 的文档签名服务。
添加 LTV 的代码如下:
public void AddLtv(string src, string dest, IOcspClient ocsp, ICrlClient crl, ITSAClient tsa)
{
using (PdfReader r = new PdfReader(src))
{
using (FileStream fos =new FileStream(dest,FileMode.CreateNew))
{
PdfStamper stp = new PdfStamper(r, fos, '[=10=]', true);
LtvVerification v = stp.LtvVerification;
AcroFields fields = stp.AcroFields;
List<String> names = fields.GetSignatureNames();
String sigName = names[names.Count - 1];
PdfPKCS7 pkcs7 = fields.VerifySignature(sigName);
if (pkcs7.IsTsp)
{
v.AddVerification(sigName, ocsp, crl,
LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
else
{
foreach (var name in names)
{
v.AddVerification(name, ocsp, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
}
stp.Close();
}
}
}
编辑: 我认为我在代码中操作 pdf 的方式导致 reading/writing pdf 出现问题。不知何故,我无法获得任何 pdf 验证器,它可以识别@mkl 提到的关于交叉 pdf 参考的问题。然而,如果我如何操作 pdf 有任何问题,我将如下共享我的代码。帮助将不胜感激。
添加新签名后,此 pdf 的旧签名将失效。如果我添加 LTV,那么即使是单个签名也是无效的。
未签名的 pdf URL: https://www.sendspace.com/file/n0ckem
没有 LTV 的签名 pdf URL:https://www.sendspace.com/file/t1gwp9
带有 LTV 单一签名的签名 pdf:https://www.sendspace.com/file/ba8leq
带有 LTV 两个签名的签名 pdf:https://www.sendspace.com/file/6b53z1
下面用于创建空容器和添加签名的代码:
private async Task<string> SignPdf(string ocspResponse, string cert, string unsignedPdf, DocumentShapeModel annotations, string caCertraw, int pageHeight, UserProfileModel user)
{
var trustedSignedpdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString(), "trustedSignedpdf.pdf");
if (!Directory.Exists(Path.GetDirectoryName(trustedSignedpdf)))
{
Directory.CreateDirectory(trustedSignedpdf);
}
var tempPdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString());
if (!Directory.Exists(tempPdf))
{
Directory.CreateDirectory(tempPdf);
}
tempPdf = Path.Combine(tempPdf, "tempSignedpdfglobal.pdf");
string finalsignedPdf = trustedSignedpdf;
var ocsp = new OcspClientBouncyCastle();
byte[] oc2 = Convert.FromBase64String(oc1);
OcspResp ocspResp = new OcspResp(oc2);
BasicOcspResp basicResp = (BasicOcspResp)ocspResp.GetResponseObject();
byte[] oc = basicResp.GetEncoded();
bool check = false;
string hexencodedDigest = null;
PdfPKCS7 sgn = null;
byte[] hash = null;
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[2];
var cer = new Org.BouncyCastle.X509.X509CertificateParser()
.ReadCertificate((new X509Certificate2(cert)).GetRawCertData());
chain[0] = cer;
var caCert = new Org.BouncyCastle.X509.X509CertificateParser()
.ReadCertificate((new X509Certificate2(caCertraw)).GetRawCertData());
chain[1] = caCert;
while (!check)
{
PdfReader.unethicalreading = true;
//create empty signature
using (PdfReader reader = new PdfReader(unsignedPdf))
{
using (FileStream os = File.OpenWrite(tempPdf))
{
PdfStamper pdfStamper = PdfStamper.CreateSignature(reader, os, '[=11=]', null, true);
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
// Sets Signature Appearance
signatureAppearance.Certificate = chain[0];
signatureAppearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
signatureAppearance.Reason = "E Signed by " + user.FirstName + " " + user.LastName + " (" + user.Email + ").";
signatureAppearance.Acro6Layers = false;
signatureAppearance.Layer4Text = PdfSignatureAppearance.questionMark;
float shapeH = annotations.IsResponsive == true ? annotations.h : ((annotations.h * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeX = annotations.IsResponsive == true ? annotations.x : ((annotations.x * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeY = annotations.IsResponsive == true ? annotations.y : ((annotations.y * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeW = annotations.IsResponsive == true ? annotations.w : ((annotations.w * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
double yaxis = (float)Convert.ToDouble(pageHeight) - (shapeH + shapeY);
// Sets Layer2 text and acro6layers
signatureAppearance.Layer2Text = " "; //Left blank so that it do not overwrite Esignature.
signatureAppearance.SetVisibleSignature(new iTextSharp.text.Rectangle((int)(shapeX), (int)yaxis, (int)(shapeX) + (int)shapeW, (int)yaxis + (int)shapeH), annotations.p, annotations.Id.ToString());
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(signatureAppearance, external, 8192);
Stream data = signatureAppearance.GetRangeStream();
string hashAlgorithm = "SHA256";
sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
hash = DigestAlgorithms.Digest(data, hashAlgorithm);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, oc, null, CryptoStandard.CADES);
//create sha256 message digest
using (SHA256.Create())
{
sh = SHA256.Create().ComputeHash(sh);
}
//create hex encoded sha256 message digest
hexencodedDigest = new BigInteger(1, sh).ToString(16);
hexencodedDigest = hexencodedDigest.ToUpper();
if (hexencodedDigest.Length == 64)
{
check = true;
}
}
}
}
var identityGetResult = await IdentityGet(_appConfiguration.TrustedSignSettings.Url + "/identity", AccessToken, IdentityJson, hexencodedDigest);
//decode hex
byte[] dsg = FromHex(identityGetResult);
//include signature on PDF
sgn.SetExternalDigest(dsg, null, "RSA");
//create TimeStamp Client
ITSAClient tsc = new DssClient(AccessToken, _env, _appConfiguration.TrustedSignSettings.Url);
//byte[] ocspResponse = ocsp.GetEncoded(chain[0],chain[chain.Length -1], CertificateUtil.GetCRLURL(chain[0]));
//Collection<byte[]> crlBytes = CertificateUtil.fetchCrlBytes(x509certificate, chain);
byte[] encodedpkcs7 = sgn.GetEncodedPKCS7(hash, tsc, oc, null, CryptoStandard.CADES);
//adds PKCS7 format Signature on empty signature container
CreateSignature(tempPdf, finalsignedPdf, annotations.Id.ToString(), encodedpkcs7);
var finaltrustedSignedpdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString());
if (!Directory.Exists(finaltrustedSignedpdf))
{
Directory.CreateDirectory(finaltrustedSignedpdf);
}
finaltrustedSignedpdf = Path.Combine(finaltrustedSignedpdf, "FinaltrustedSignedpdf.pdf");
//adds LTV to signed document
AddLtv(finalsignedPdf, finaltrustedSignedpdf, ocsp, new CrlClientOnline(), tsc);
return finaltrustedSignedpdf;
}
用于创建签名
public void CreateSignature(string src, string dest, string fieldname, byte[] sig)
{
using (PdfReader reader = new PdfReader(src))
{
using (FileStream os = File.OpenWrite(dest))
{
IExternalSignatureContainer external = new MyExternalSignatureContainer(sig);
MakeSignature.SignDeferred(reader, fieldname, os, external);
}
}
}
原始 PDF 的交叉引用 table 中存在错误。众所周知,Adobe 签名验证对此类错误很敏感(请参阅 and ),在某些情况下,它会将此类文件的签名显示为无效。
您应该要求该文档的来源提供没有该错误的版本
详情
文档的第一个未签名修订版的交叉引用 table 如下所示:
xref
0 55
0000000000 65535 f
0000000018 00000 n
0000000164 00000 n
0000000216 00000 n
0000000554 00000 n
0000003363 00000 n
0000003529 00000 n
0000003764 00000 n
0000003815 00000 n
0000003866 00000 n
0000004038 00000 n
0000004279 00000 n
0000004439 00000 n
0000004662 00000 n
0000004792 00000 n
0000004818 00000 n
0000004991 00000 n
0000005061 00000 n
0000005297 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000005466 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000006188 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000006236 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
54 18
0000006284 00000 n
0000006350 00000 n
0000006648 00000 n
0000171077 00000 n
0000171435 00000 n
0000171726 00000 n
0000171973 00000 n
0000323100 00000 n
0000323123 00000 n
0000324290 00000 n
0000324333 00000 n
0000324715 00000 n
0000326153 00000 n
0000328056 00000 n
0000328093 00000 n
0000328132 00000 n
0000328214 00000 n
0000328377 00000 n
如您所见,它由两个小节组成,第一个小节包含从 0 开始的 55 个对象,第二个小节包含从 54 开始的 18 个对象。
这是无效的,原因有二:
首先(正如上面引用的两个答案中所解释的那样)初始 PDF 修订版的交叉引用 table 必须仅包含一个部分!
For a file that has never been incrementally updated, the cross-reference section shall contain only one subsection, whose object numbering begins at 0.
(ISO 32000-1 和 ISO 32000-2,在这两种情况下第 7.5.4 节 "Cross-Reference Table")
此外,那个交叉引用 table 有两个针对同一个对象的条目,第一小节的最后一个条目和第二小节的第一个条目都与对象 54 相关。这也被禁止:
A given object number shall not have an entry in more than one subsection within a single section.
(同上)
根据相应代码的详细信息,在使用某些 PDF 处理器处理 PDF 时,这可能会或可能不会导致任意问题,例如Adobe Acrobat Reader.
您的编辑
在您的编辑中,您共享了一些文件。特别是你分享了
VeriFinger_SDK_Brochure_2017-12-27.pdf
unsigned pdf URL: https://www.sendspace.com/file/n0ckem
VeriFinger_SDK_Brochure_signed_witoutltv.Pdf
Signed pdf without LTV URL : https://www.sendspace.com/file/t1gwp9
FinaltrustedSignedpdf.pdf
Signed pdf with LTV single sign: https://www.sendspace.com/file/ba8leq
FinaltrustedSignedpdf.pdf(同名不同)
Signed pdf with LTV two sign: https://www.sendspace.com/file/6b53z1
根据您的代码,您在追加模式下应用了所有更改。因此,后三个文件每个都必须由第一个文件 VeriFinger_SDK_Brochure_2017-12-27.pdf 加上一些附加数据组成。 但事实并非如此,后三个文件实际上都比第一个短。因此,我必须假设第一个文件首先以某种方式处理然后签名。
现看"original file"VeriFinger_SDK_Brochure_2017-12-27.pdf的交叉引用table(直接在文本中打开即可查看器并滚动到它的末尾)我们看到它是一个整体,只是一个小节。它包含许多标记为 free 但没有间隙的条目。
查看后三个文件的第一个修订版的交叉引用 table,我们发现每个文件都分为多个小节。显然,标记为 free 的条目已从 table 中删除,导致 table 包含许多小节。可能这已被设计为优化尝试,但结果是损坏的 PDF。
因此,无论您在签名前对文件应用何种 PDF 处理器,该处理器都会损坏 PDF。
损坏PDF的PDF处理器
比较原始文件的文档信息和其他三个文件中的初始修订,在文件签名之前处理文件的 PDF 处理器似乎是 Aspose.PDF for .NET 19.1 因为 Producer 值已更改为那个值。
事实上,这似乎是一个已知的 Aspose 问题,例如参见 Aspose 免费支持论坛上的 PDF/A-1 conversion creates invalid XRef table 线程,该线程于 2016 年 8 月开始。
它已被归档为 PDFNET-41272 并在 2017 年 2 月的 .NET 17.2.0 Aspose.Pdf 中标记为已修复,但正如同一个月在该论坛帖子中所报道的那样,它并不是真的完全固定。
显然 Aspose 还没有修复这个错误,并且仍在努力。
将 LTV 添加到数字签名后,它显示文档已更改。
从这个问题中获取参考后:After LTV Certification Signature, PDF shows "Document has been Changed"
我对我的代码进行了更改,它适用于所有文档,但对于此文档:https://www.sendspace.com/file/3ulwn7 - 它显示无效签名。
我们也在使用来自 global sign 的文档签名服务。
添加 LTV 的代码如下:
public void AddLtv(string src, string dest, IOcspClient ocsp, ICrlClient crl, ITSAClient tsa)
{
using (PdfReader r = new PdfReader(src))
{
using (FileStream fos =new FileStream(dest,FileMode.CreateNew))
{
PdfStamper stp = new PdfStamper(r, fos, '[=10=]', true);
LtvVerification v = stp.LtvVerification;
AcroFields fields = stp.AcroFields;
List<String> names = fields.GetSignatureNames();
String sigName = names[names.Count - 1];
PdfPKCS7 pkcs7 = fields.VerifySignature(sigName);
if (pkcs7.IsTsp)
{
v.AddVerification(sigName, ocsp, crl,
LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
else
{
foreach (var name in names)
{
v.AddVerification(name, ocsp, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
}
stp.Close();
}
}
}
编辑: 我认为我在代码中操作 pdf 的方式导致 reading/writing pdf 出现问题。不知何故,我无法获得任何 pdf 验证器,它可以识别@mkl 提到的关于交叉 pdf 参考的问题。然而,如果我如何操作 pdf 有任何问题,我将如下共享我的代码。帮助将不胜感激。
添加新签名后,此 pdf 的旧签名将失效。如果我添加 LTV,那么即使是单个签名也是无效的。
未签名的 pdf URL: https://www.sendspace.com/file/n0ckem
没有 LTV 的签名 pdf URL:https://www.sendspace.com/file/t1gwp9
带有 LTV 单一签名的签名 pdf:https://www.sendspace.com/file/ba8leq
带有 LTV 两个签名的签名 pdf:https://www.sendspace.com/file/6b53z1
下面用于创建空容器和添加签名的代码:
private async Task<string> SignPdf(string ocspResponse, string cert, string unsignedPdf, DocumentShapeModel annotations, string caCertraw, int pageHeight, UserProfileModel user)
{
var trustedSignedpdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString(), "trustedSignedpdf.pdf");
if (!Directory.Exists(Path.GetDirectoryName(trustedSignedpdf)))
{
Directory.CreateDirectory(trustedSignedpdf);
}
var tempPdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString());
if (!Directory.Exists(tempPdf))
{
Directory.CreateDirectory(tempPdf);
}
tempPdf = Path.Combine(tempPdf, "tempSignedpdfglobal.pdf");
string finalsignedPdf = trustedSignedpdf;
var ocsp = new OcspClientBouncyCastle();
byte[] oc2 = Convert.FromBase64String(oc1);
OcspResp ocspResp = new OcspResp(oc2);
BasicOcspResp basicResp = (BasicOcspResp)ocspResp.GetResponseObject();
byte[] oc = basicResp.GetEncoded();
bool check = false;
string hexencodedDigest = null;
PdfPKCS7 sgn = null;
byte[] hash = null;
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[2];
var cer = new Org.BouncyCastle.X509.X509CertificateParser()
.ReadCertificate((new X509Certificate2(cert)).GetRawCertData());
chain[0] = cer;
var caCert = new Org.BouncyCastle.X509.X509CertificateParser()
.ReadCertificate((new X509Certificate2(caCertraw)).GetRawCertData());
chain[1] = caCert;
while (!check)
{
PdfReader.unethicalreading = true;
//create empty signature
using (PdfReader reader = new PdfReader(unsignedPdf))
{
using (FileStream os = File.OpenWrite(tempPdf))
{
PdfStamper pdfStamper = PdfStamper.CreateSignature(reader, os, '[=11=]', null, true);
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
// Sets Signature Appearance
signatureAppearance.Certificate = chain[0];
signatureAppearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
signatureAppearance.Reason = "E Signed by " + user.FirstName + " " + user.LastName + " (" + user.Email + ").";
signatureAppearance.Acro6Layers = false;
signatureAppearance.Layer4Text = PdfSignatureAppearance.questionMark;
float shapeH = annotations.IsResponsive == true ? annotations.h : ((annotations.h * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeX = annotations.IsResponsive == true ? annotations.x : ((annotations.x * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeY = annotations.IsResponsive == true ? annotations.y : ((annotations.y * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
float shapeW = annotations.IsResponsive == true ? annotations.w : ((annotations.w * 72 / 150) / (float)Convert.ToDouble(annotations.ratio));
double yaxis = (float)Convert.ToDouble(pageHeight) - (shapeH + shapeY);
// Sets Layer2 text and acro6layers
signatureAppearance.Layer2Text = " "; //Left blank so that it do not overwrite Esignature.
signatureAppearance.SetVisibleSignature(new iTextSharp.text.Rectangle((int)(shapeX), (int)yaxis, (int)(shapeX) + (int)shapeW, (int)yaxis + (int)shapeH), annotations.p, annotations.Id.ToString());
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(signatureAppearance, external, 8192);
Stream data = signatureAppearance.GetRangeStream();
string hashAlgorithm = "SHA256";
sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
hash = DigestAlgorithms.Digest(data, hashAlgorithm);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, oc, null, CryptoStandard.CADES);
//create sha256 message digest
using (SHA256.Create())
{
sh = SHA256.Create().ComputeHash(sh);
}
//create hex encoded sha256 message digest
hexencodedDigest = new BigInteger(1, sh).ToString(16);
hexencodedDigest = hexencodedDigest.ToUpper();
if (hexencodedDigest.Length == 64)
{
check = true;
}
}
}
}
var identityGetResult = await IdentityGet(_appConfiguration.TrustedSignSettings.Url + "/identity", AccessToken, IdentityJson, hexencodedDigest);
//decode hex
byte[] dsg = FromHex(identityGetResult);
//include signature on PDF
sgn.SetExternalDigest(dsg, null, "RSA");
//create TimeStamp Client
ITSAClient tsc = new DssClient(AccessToken, _env, _appConfiguration.TrustedSignSettings.Url);
//byte[] ocspResponse = ocsp.GetEncoded(chain[0],chain[chain.Length -1], CertificateUtil.GetCRLURL(chain[0]));
//Collection<byte[]> crlBytes = CertificateUtil.fetchCrlBytes(x509certificate, chain);
byte[] encodedpkcs7 = sgn.GetEncodedPKCS7(hash, tsc, oc, null, CryptoStandard.CADES);
//adds PKCS7 format Signature on empty signature container
CreateSignature(tempPdf, finalsignedPdf, annotations.Id.ToString(), encodedpkcs7);
var finaltrustedSignedpdf = Path.Combine(_env.WebRootPath, "TempPath", annotations.userId, annotations.Id.ToString());
if (!Directory.Exists(finaltrustedSignedpdf))
{
Directory.CreateDirectory(finaltrustedSignedpdf);
}
finaltrustedSignedpdf = Path.Combine(finaltrustedSignedpdf, "FinaltrustedSignedpdf.pdf");
//adds LTV to signed document
AddLtv(finalsignedPdf, finaltrustedSignedpdf, ocsp, new CrlClientOnline(), tsc);
return finaltrustedSignedpdf;
}
用于创建签名
public void CreateSignature(string src, string dest, string fieldname, byte[] sig)
{
using (PdfReader reader = new PdfReader(src))
{
using (FileStream os = File.OpenWrite(dest))
{
IExternalSignatureContainer external = new MyExternalSignatureContainer(sig);
MakeSignature.SignDeferred(reader, fieldname, os, external);
}
}
}
原始 PDF 的交叉引用 table 中存在错误。众所周知,Adobe 签名验证对此类错误很敏感(请参阅
您应该要求该文档的来源提供没有该错误的版本
详情
文档的第一个未签名修订版的交叉引用 table 如下所示:
xref
0 55
0000000000 65535 f
0000000018 00000 n
0000000164 00000 n
0000000216 00000 n
0000000554 00000 n
0000003363 00000 n
0000003529 00000 n
0000003764 00000 n
0000003815 00000 n
0000003866 00000 n
0000004038 00000 n
0000004279 00000 n
0000004439 00000 n
0000004662 00000 n
0000004792 00000 n
0000004818 00000 n
0000004991 00000 n
0000005061 00000 n
0000005297 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000005466 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000006188 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000006236 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
0000000000 00000 n
54 18
0000006284 00000 n
0000006350 00000 n
0000006648 00000 n
0000171077 00000 n
0000171435 00000 n
0000171726 00000 n
0000171973 00000 n
0000323100 00000 n
0000323123 00000 n
0000324290 00000 n
0000324333 00000 n
0000324715 00000 n
0000326153 00000 n
0000328056 00000 n
0000328093 00000 n
0000328132 00000 n
0000328214 00000 n
0000328377 00000 n
如您所见,它由两个小节组成,第一个小节包含从 0 开始的 55 个对象,第二个小节包含从 54 开始的 18 个对象。
这是无效的,原因有二:
首先(正如上面引用的两个答案中所解释的那样)初始 PDF 修订版的交叉引用 table 必须仅包含一个部分!
For a file that has never been incrementally updated, the cross-reference section shall contain only one subsection, whose object numbering begins at 0.
(ISO 32000-1 和 ISO 32000-2,在这两种情况下第 7.5.4 节 "Cross-Reference Table")
此外,那个交叉引用 table 有两个针对同一个对象的条目,第一小节的最后一个条目和第二小节的第一个条目都与对象 54 相关。这也被禁止:
A given object number shall not have an entry in more than one subsection within a single section.
(同上)
根据相应代码的详细信息,在使用某些 PDF 处理器处理 PDF 时,这可能会或可能不会导致任意问题,例如Adobe Acrobat Reader.
您的编辑
在您的编辑中,您共享了一些文件。特别是你分享了
VeriFinger_SDK_Brochure_2017-12-27.pdf
unsigned pdf URL: https://www.sendspace.com/file/n0ckem
VeriFinger_SDK_Brochure_signed_witoutltv.Pdf
Signed pdf without LTV URL : https://www.sendspace.com/file/t1gwp9
FinaltrustedSignedpdf.pdf
Signed pdf with LTV single sign: https://www.sendspace.com/file/ba8leq
FinaltrustedSignedpdf.pdf(同名不同)
Signed pdf with LTV two sign: https://www.sendspace.com/file/6b53z1
根据您的代码,您在追加模式下应用了所有更改。因此,后三个文件每个都必须由第一个文件 VeriFinger_SDK_Brochure_2017-12-27.pdf 加上一些附加数据组成。 但事实并非如此,后三个文件实际上都比第一个短。因此,我必须假设第一个文件首先以某种方式处理然后签名。
现看"original file"VeriFinger_SDK_Brochure_2017-12-27.pdf的交叉引用table(直接在文本中打开即可查看器并滚动到它的末尾)我们看到它是一个整体,只是一个小节。它包含许多标记为 free 但没有间隙的条目。
查看后三个文件的第一个修订版的交叉引用 table,我们发现每个文件都分为多个小节。显然,标记为 free 的条目已从 table 中删除,导致 table 包含许多小节。可能这已被设计为优化尝试,但结果是损坏的 PDF。
因此,无论您在签名前对文件应用何种 PDF 处理器,该处理器都会损坏 PDF。
损坏PDF的PDF处理器
比较原始文件的文档信息和其他三个文件中的初始修订,在文件签名之前处理文件的 PDF 处理器似乎是 Aspose.PDF for .NET 19.1 因为 Producer 值已更改为那个值。
事实上,这似乎是一个已知的 Aspose 问题,例如参见 Aspose 免费支持论坛上的 PDF/A-1 conversion creates invalid XRef table 线程,该线程于 2016 年 8 月开始。
它已被归档为 PDFNET-41272 并在 2017 年 2 月的 .NET 17.2.0 Aspose.Pdf 中标记为已修复,但正如同一个月在该论坛帖子中所报道的那样,它并不是真的完全固定。
显然 Aspose 还没有修复这个错误,并且仍在努力。