jin
jin

Reputation: 41

How to verify a custom formatted digital signature with iText?

I am now writting a pdf viewer with whom I can put a custom formatted signature (using a Chinese SM2 encryption algorithm,that why I can't use the standard verify method,and that's why I must write my own pdf viewer)into a pdf and check it.The signing part,I calculate the hash,and then I sign the hash with a usbkey,and finally I put the signature into the pdf. But the checking part,I can't find any help and I don't know how can I go.I need to find a way to get the origin byte range and calculate the hash and then read the signature from the signature form field.And compare the hash with the old one to find out if the file is changed.Could anyone give me some sample code ?

Here is some java code I found and rewrite it to c#,which I think may do some help,though some methods don't actully exist.

  PdfReader pdfReader = new PdfReader("D:\\Hello_world.pdf");
  PdfDocument pdfDocument = new PdfDocument(pdfReader);
  {
       SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
       foreach (String name in signatureUtil.GetSignatureNames())
        {

            PdfSignature signature = signatureUtil.getSignature(name);
            PdfArray b = signature.GetByteRange();
            RandomAccessFileOrArray rf = pdfReader.GetSafeFile();
            Stream rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), SignatureUtil.AsLongArray(b)));
            Stream result = TARGET_STREAM_FOR_name_BYTES;
            {
                 byte[] buf = new byte[8192];
                 int rd;
                 while ((rd = rg.Read(buf, 0, buf.Length)) > 0)
                 {
                      result.Write(buf, 0, rd);
                  }
             }

          }
    }

Upvotes: 1

Views: 1399

Answers (1)

Uladzimir Asipchuk
Uladzimir Asipchuk

Reputation: 2458

To tell whether the file has been changed after signing one can use SignatureUtl#verifySignature together with PdfPKCS7#verify.

Let's look at one of the official iText samples to find out how it can be done (it's been written in Java, but there should be no problem for you to port it to C# since the api is exactly the same): https://github.com/itext/i7js-signatures/blob/develop/src/test/java/com/itextpdf/samples/signatures/chapter05/C5_01_SignatureIntegrity.java

More precisely, you're interested in the next snippet:

 public PdfPKCS7 verifySignature(SignatureUtil signUtil, String name) throws GeneralSecurityException, IOException {
    System.out.println("Signature covers whole document: " + signUtil.signatureCoversWholeDocument(name));
    System.out.println("Document revision: " + signUtil.getRevision(name) + " of " + signUtil.getTotalRevisions());
    PdfPKCS7 pkcs7 = signUtil.verifySignature(name);
    System.out.println("Integrity check OK? " + pkcs7.verify());
    return pkcs7;
}

Note that the SignatureUtil#verifySignature doesn't actually check the signature's integrity, but only some of its properties. Its main purpose is to create a PdfPKCS7 object which than can be used to check signature's integrity with PdfPKCS7#verify.

That's important to mention that the methods above do not check whether the certificates, which haved been used to sign the document, are valid. They should be (if necessary) checked separetely.

In general I advise you to read an overview of the iText signing functionality (the book is free of charge). Although the book was written for iText5, one can find fully ported iText7 examples on iText's github page: https://github.com/itext/i7js-signatures

P.S. Since you didn't tell us which iText version you use, I've given you an answer in the most recent one: iText7. However since the signing functionality has been just ported to iText7 from iText5, it's easy to reproduce the answer in iText5. Just study the same example repos: the Java one and the C# one.

Upvotes: 1

Related Questions