签名对于使用iText的PDF文件无效 [英] Signature is Invalid for PDF File with iText

查看:234
本文介绍了签名对于使用iText的PDF文件无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用swisscom数字签名服务,并且我们有一个测试帐户.好吧,该服务需要哈希码为pdf文件.我们用

I am using swisscom digital signature service and we have a test account. Well the service requires the hash code the pdf file . We send it with

DIGEST_VALUE = $(openssl dgst -binary -SHA256 $ FILE | openssl enc -base64 -A)

DIGEST_VALUE=$(openssl dgst -binary -SHA256 $FILE | openssl enc -base64 -A)

,我得到PKCS#7响应.您可以使用以下网站解码我的签名回复: https://certlogik.com/decoder/ 并且签名内容为 http://not_need_anymore

and I get a PKCS#7 response. You can decode the my signature response by using this website https://certlogik.com/decoder/ and the signature content is http://not_need_anymore

我有以下相同的问题(因为我们使用相同的代码)

I have the same problem as follow (because we use the same code)

数字签名(PKCS#7-延期签名)/自从应用签名以来,文档已被更改或损坏

我的回复被加密为sha256. 好吧,我正在使用带有C#的iText来签署pdf文件.我签名并看到一些详细信息(例如原因,位置等).

my response has been with sha256 crypted. Well I am using iText with c# to sign the pdf file. I sign and I see some details (such as reason, location etc).

这是一种创建带有签名字段的pdf文件的方法

here is the method that creates a pdf file with a signature field

public static string GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName)
{
    if (File.Exists(tempPdf))
        File.Delete(tempPdf);

    using (PdfReader reader = new PdfReader(unsignedPdf))
    {
        using (FileStream os = File.OpenWrite(tempPdf))
        {
            PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
            PdfSignatureAppearance appearance = stamper.SignatureAppearance;
            appearance.SetVisibleSignature(new Rectangle(36, 748, 250, 400), 1, signatureFieldName);

            //IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
            IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
            PdfSignature external2 = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);//ADBE_PKCS7_SHA1);
//as pdf name I tried also PdfName.ETSI_RFC3161
//(ref => https://github.com/SCS-CBU-CED-IAM/itext-ais/blob/master/src/com/swisscom/ais/itext/PDF.java)

            appearance.Reason = "For archive";
            appearance.Location = "my loc";
            appearance.SignDate = DateTime.Now;
            appearance.Contact = "myemail@domain.ch";
            appearance.CryptoDictionary = external2;

            var level = reader.GetCertificationLevel();
            // check: at most one certification per pdf is allowed
            if (level != PdfSignatureAppearance.NOT_CERTIFIED)
                throw new Exception("Could not apply -certlevel option. At most one certification per pdf is allowed, but source pdf contained already a certification.");
            appearance.CertificationLevel = level;

            MakeSignature.SignExternalContainer(appearance, external,30000);

            byte[] array = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());

            return Convert.ToBase64String(array);
        }
    }
}

精算师,我不使用此方法返回的内容.因为它已经创建了带有签名字段的临时pdf文件.

Actualls I do not use what this method returns. Because it already creates a temp pdf file with signature field.

之后,我给出此pdf文件的哈希码,并获得PKCS#7响应.然后使用以下功能,将签名添加到pdf(它会创建另一个pdf文件).

After that,I give the hash code of this pdf file and get PKCS#7 responde. and then using the following function, I am adding the signature to a pdf (it creates another pdf file).

public static void EmbedSignature(string tempPdf, string signedPdf,
                                  string signatureFieldName, string signature)
{
    byte[] signedBytes = Convert.FromBase64String(signature);

    using (PdfReader reader = new PdfReader(tempPdf))
    {
        using (FileStream os = File.OpenWrite(signedPdf))
        {
            IExternalSignatureContainer external = 
                                            new MyExternalSignatureContainer(signedBytes);

            MakeSignature.SignDeferred(reader, signatureFieldName, os, external);
        }
    }
}

方法中的签名参数,我给p7s文件内容如下

the signature parameter in the method, I give p7s file content as follows

string signatureContent = File.ReadAllText(@"mypath\signed_cert.p7s");

signatureContent = signatureContent
                                   .Replace("-----BEGIN PKCS7-----\n", "")
                                   .Replace("-----END PKCS7-----\n","").Trim();

我想念什么或做错什么了?

what am I missing or doing wrong?

推荐答案

与对整个签名文件进行签名的常规分离签名相反,PDF中的集成签名会签名(并且只能签名),但留给该签名的空间除外.签名本身.

In contrast to the regular detached signatures which sign the whole signed file, integrated signatures in PDFs sign (and can only sign) everything but the space set aside for the signature itself.

(有关更多背景信息,请阅读此答案)

因此,当您使用占位符准备要嵌入签名的PDF后

Thus, when you after preparing the PDF with a placeholder to embed the signature

给出此pdf文件的哈希码并获得PKCS#7响应

give the hash code of this pdf file and get PKCS#7 responde

您散列太多,因为您的散列包含了实际签名的(然后为空,即用'0'字符填充)占位符.相反,方法GetBytesToSign仅返回有符号字节范围内的哈希,即除占位符之外的所有内容:

you hash too much because your hashing included the (then empty, i.e. filled with '0' characters) placeholder for the actual signature. The method GetBytesToSign instead only returns the hash over the signed byte ranges, i.e. everything but the placeholder:

byte[] array = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());

您必须采用该值,或者类似地仅对签名的占位符以外的所有内容进行散列.

You have to either takes this value or similarly hash only everything but the placeholder for the signature.

这篇关于签名对于使用iText的PDF文件无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆