WinRT应用程序中的PDF数字签名无效 [英] Invalid PDF digital signature in WinRT app
问题描述
我正在尝试移植一个有效的解决方案,用于将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屋!