繁体   English   中英

WinRT应用程序中的无效PDF数字签名

[英]Invalid PDF digital signature in WinRT app

我正在尝试将用于将PDF从标准C#类库签名到便携式类库(或Windows Store App 8.1)的可行解决方案。 iTextSharp版本:5.5.3.0

逻辑如下:我在iTextSharp中创建一个签名外观,对其进行哈希处理(SHA256,这是第三方要求),将哈希发送到Web服务,该服务向我返回已签名的内容。

如前所述,该解决方案在ASP.net Web应用程序中运行良好,但是所有在WinRT环境中实施该解决方案的尝试似乎都失败了-已应用签名,但无效:PDF阅读器的消息:“文档已更改或自签名被应用以来已损坏”。

在分析了代码差异之后,在这种情况下似乎与我相关的唯一差异是哈希部分。 在标准C#类库中,我像这样解决了它,并使其与有效签名一起工作:

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的库部分不同,因此我尝试使用不同的类来实现哈希:

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发送到Web服务,以相同的方式获取响应并将其放入文件中,但是签名无效。

我想念什么?

WinRT版本中的问题在于它会忽略哈希循环中的read值:

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

特别是最后一个块通常不会完全填满缓冲区buff ,因此最后一个hasher.Append调用将对最后一个块加上一些尾随的垃圾字节进行哈希处理,这会伪造结果。

您只能哈希buff的前read字节。

OP最终像这样解决了它:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM