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?