【问题标题】:Invalid PDF digital signature in WinRT appWinRT 应用程序中的 PDF 数字签名无效
【发布时间】:2014-11-11 16:01:08
【问题描述】:

我正在尝试将用于签署 PDF 的工作解决方案从标准 C# 类库移植到可移植类库(或 Windows 商店应用程序 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发送给webservice,获取响应并以同样的方式放入文件中,但是签名无效。

我错过了什么?

【问题讨论】:

  • 我错过了什么? - 你忽略了 read 值。特别是最后一个块通常不会完全填满buff,所以你最后一个hasher.Append 调用将散列最后一个块加上一些尾随垃圾字节,这会伪造你的结果。您只能散列您的buff 的第一个read 字节。
  • Lukasz,您能否至少看看您之前的问题(关于同一主题)并在继续之前澄清其中的一些困惑?
  • @mkl 你是对的!这就是重点。非常非常感谢!
  • @owlstead 是的,我会看看并告诉你们,现在这个案子已经解决了,它帮助我更好地理解了另一个问题。感谢您提供的所有宝贵帮助!
  • @lukasz 好的,我会将评论作为答案,以免您的问题悬而未决。

标签: c# windows-runtime windows-store-apps itextsharp digital-signature


【解决方案1】:

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());
}

【讨论】:

  • 是的,工作代码可能如下所示:while ((read = await sapStream.ReadAsync(buff, 0, 8192)) &gt; 0) { byte[] newArr = new byte[read]; Array.Copy(buff, newArr, read); hasher.Append(newArr.AsBuffer()); }) 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 2016-05-09
  • 1970-01-01
相关资源
最近更新 更多