Invalid PDF digital signature in WinRT app

橙三吉。 提交于 2019-12-25 00:52:23

问题


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

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.

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".

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

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

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.

What am I missing?


回答1:


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

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.

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

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


来源:https://stackoverflow.com/questions/26869058/invalid-pdf-digital-signature-in-winrt-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!