WinRT应用程序中的PDF数字签名无效 [英] Invalid PDF digital signature in WinRT app

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

问题描述

我正在尝试移植一个有效的解决方案,用于将PDF从标准C#类库签名到可移植类库(或Windows应用商店8.1)。 iTextSharp版本:5.5.3.0

I am trying to port a working solution for signing PDFs from a standard C# class library to portable class library (or windows store app 8.1). iTextSharp version: 5.5.3.0

逻辑如下:我在iTextSharp中创建一个签名外观,哈希它(SHA256,它是第三方要求),发送哈希到web服务,它返回签名的内容。

The logic is as follows: I create a signature appearance in iTextSharp, hash it (SHA256, it's a third party requirement), send the hash to a webservice which returns me the signed content.

如上所述,解决方案工作正常,例如在ASP.net Web应用程序中,但在WinRT环境中实现它的所有尝试似乎都失败了 - 签名被应用,但是它无效:来自PDF阅读器的消息:自应用签名以来,文档已被更改或损坏。

As mentioned, the solution is working fine e.g. in ASP.net web applications, but all the attempts to implement it in the WinRT environment seem to fail - the signature is applied, but it's invalid: message from PDF reader: "document has been altered or corrupted since the Signature was applied".

在分析代码差异之后,在这种情况下,与我相关的唯一差异是散列部分。在标准的C#类库中,我已经解决了这个问题,结果使用了有效的签名:

After analyzing the code differences, the only difference which seems relevant to me in this case is the hashing part. In the standard C# class library, I had it solved like that, and got it working with valid signatures as a result:

PdfSignatureAppearance sap = stp.SignatureAppearance;
// some appearance properties are filled here...

PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.Date = new PdfDate(sap.SignDate);
dic.Reason = sap.Reason;
dic.Location = sap.Location;
sap.CryptoDictionary = dic;

Dictionary<PdfName, int> exc = new Dictionary<PdfName, int>();
exc.Add(PdfName.CONTENTS, csize * 2 + 2);
sap.PreClose(exc);

HashAlgorithm sha = new SHA256CryptoServiceProvider();
var sapStream = sap.GetRangeStream();
int read = 0;
byte[] buff = new byte[8192];
while ((read = sapStream.Read(buff, 0, 8192)) > 0)
{
    sha.TransformBlock(buff, 0, read, buff, 0);
}
sha.TransformFinalBlock(buff, 0, 0);

// here I am sending the hash to the third party webservice, 
// obtaining the 'signed' response
byte[] outc = new byte[csize];
PdfDictionary dic2 = new PdfDictionary();

Array.Copy(response, 0, outc, 0, response.Length);
dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));               
sap.Close(dic2);

由于WinRT的库有所不同,我尝试使用不同的类实现散列:

Since the libraries for WinRT are partly different, I try to implement the hashing using different class:

var sapStream = sap.GetRangeStream();
HashAlgorithmProvider alg = Windows.Security.Cryptography.Core.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var hasher = alg.CreateHash();
int read = 0;
byte[] buff = new byte[8192];
while ((read = await sapStream.ReadAsync(buff, 0, 8192)) > 0)
{
   hasher.Append(buff.AsBuffer());
}

String hashText = CryptographicBuffer.EncodeToBase64String(hasher.GetValueAndReset());

然后我将hashText发送到webservice,获取响应并将其放入文件中同样的方式,但签名无效。

Then I am sending the hashText to the webservice, obtain the response and put it into the file in the same manner, but the signature is invalid.

我缺少什么?

推荐答案

WinRT版本中的问题是它忽略了散列循环中的读取值:

The issue in the WinRT version is that it ignores the read value in the hashing loop:

int read = 0;
byte[] buff = new byte[8192];
while ((read = await sapStream.ReadAsync(buff, 0, 8192)) > 0)
{
   hasher.Append(buff.AsBuffer());
}

特别是最后一个块通常不会完全填充缓冲区 buff ,所以最后一个 hasher.Append 调用将散列最后一个块加上一些尾随垃圾字节,这会伪造结果。

Especially the last block normally will not fully fill the buffer buff, so the last hasher.Append call will hash the final block plus some trailing trash bytes which falsify the result.

您只能散列 buff 个字节c $ c>。

You may only hash the first read bytes of your buff.

OP最终解决了这个问题:

The OP eventually solved it like this:

while ((read = await sapStream.ReadAsync(buff, 0, 8192)) > 0)
{
    byte[] newArr = new byte[read];
    Array.Copy(buff, newArr, read);
    hasher.Append(newArr.AsBuffer());
}

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

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