使用iText的PDF文件的签名无效

时间:2018-03-27 11:11:03

标签: c# pdf itext digital-signature

我正在使用swisscom数字签名服务,我们有一个测试帐户。那么服务需要哈希代码pdf文件。我们发送

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

我得到了PKCS#7回复。您可以使用此网站解析我的签名回复https://certlogik.com/decoder/ 签名内容为http://not_need_anymore

我遇到同样的问题(因为我们使用相同的代码)

Digital Signature (PKCS#7 - Deferred Signing) / The document has been altered or corrupted since the signature was applied

我的回答是sha256加密了。 好吧,我正在使用带有c#的iText来签署pdf文件。我签名并且我看到一些细节(例如原因,位置等)。

这是创建带有签名字段

的pdf文件的方法
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);
        }
    }
}

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

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

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文件内容如下

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

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

我错过了什么或做错了什么?

1 个答案:

答案 0 :(得分:1)

与签署整个签名文件的常规分离签名相比,PDF中的集成签名会签署(并且只能签名)除签名本身之外的所有空间。

enter link description here

(有关更多背景,请阅读this answer

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

之后
  

提供此pdf文件的哈希码并获取PKCS#7 responde

你散列太多,因为你的散列包括实际签名的(然后是空的,即填充'0'字符)占位符。方法GetBytesToSign只返回有符号字节范围的哈希值,即除占位符之外的所有内容:

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

您必须获取此值或类似地仅散列除签名占位符之外的所有内容。