OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

Signing a PDF with an external signature using a smartcard using iTextSharp 5 gives formatting errors C#

  • Thread starter Thread starter Hasabe
  • Start date Start date
H

Hasabe

Guest
I'm trying to implement a PDF signature with a smartcard using iText 5.5.11. The smart card itself is a Mongolian national ID card which itself seems to be a type of Gemalto. I don't have the dll so I've implemented the iExternalSignature with APDU commands. The signed PDF says it's signed by Unknown and error encountered while BER decoding. There's a certificate file already extracted from the smart card and on the computer. SmartCardHandler is a handler for sending and receiving APDU commands.

Here's my SignPdf implementation.

Code:
        private static void SignPdf(string pdfPath, string signedPdfPath, SmartCardHandler handler, string certificatePath)
        {
            using (PdfReader reader = new PdfReader(pdfPath))
            using (FileStream os = new FileStream(signedPdfPath, FileMode.Create))
            {
                X509Certificate2 cert = new X509Certificate2(certificatePath);
                Org.BouncyCastle.X509.X509Certificate bouncyCert = ConvertToBouncyCastle(cert);
                List<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate> { bouncyCert };

                PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
                PdfSignatureAppearance appearance = stamper.SignatureAppearance;
                appearance.Reason = "reason";
                appearance.Location = "location";
                appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(0, 0, 200, 100), 1, "sig");
                appearance.Certificate = chain[0];
                
                IExternalSignature external = new SmartCardSignature(handler);

                MakeSignature.SignDetached(appearance, external, chain, null, null, null, 0, CryptoStandard.CMS);
            }
        }

and here is my external signature implementation

Code:
class SmartCardSignature : IExternalSignature
{
    private readonly SmartCardHandler _handler;

    public SmartCardSignature(SmartCardHandler handler)
    {
        _handler = handler;
    }

    public byte[] Sign(byte[] message)
    {
        IDigest messageDigest = DigestUtilities.GetDigest(GetHashAlgorithm());
        byte[] hash = DigestAlgorithms.Digest(messageDigest, message);

        byte[] sendHash = new byte[] { 0x00, 0x2A, 0x90, 0xA0, 0x22, 0x90, 0x20, (byte)hash.Length }.Concat(hash).ToArray();
        _handler.SendApduCommand(sendHash);
        byte[] getHash = new byte[] { 0x00, 0xC0, 0x00, 0x00, 0x20 };
        _handler.SendApduCommand(getHash);
        byte[] signApdu = new byte[] { 0x00, 0x2A, 0x9E, 0x9A, 0x00 };
        byte[] signatureWith9000 = _handler.SendApduCommand(signApdu);;

        if (signatureWith9000.Length < 2 || signatureWith9000[^2] != 0x90 || signatureWith9000[^1] != 0x00)
        {
            throw new InvalidOperationException("Failed to sign the message using the smart card.");
        }

        byte[] signature = signatureWith9000.Take(signatureWith9000.Length - 2).ToArray();
        return signature;
    }

    public string GetHashAlgorithm() => "SHA-256";

    public string GetEncryptionAlgorithm() => "RSA";
}

here's a test pdf before signing

and here's an example cms signed pdf

and here's an example cades (not sure) signed pdf

here's the apdu trace, pin code is 1111

Code:
00 A4 04 00 0C A0 00 00 00 18 40 00 00 01 63 42 00 
90 00 
00 20 00 81 08 31 31 31 31 30 30 30 30 
90 00 
00 22 41 B6 06 84 01 02 80 01 42 
90 00 
00 2A 90 A0 22 90 20 20 0B 2D C2 F7 37 64 BE 40 F9 F3 4C 33 F9 BA F5 4E 49 06 4D 63 C1 B7 CA 51 DD 19 46 08 21 C7 AC 90 
61 20 
00 C0 00 00 20 
20 0B 2D C2 F7 37 64 BE 40 F9 F3 4C 33 F9 BA F5 4E 49 06 4D 63 C1 B7 CA 51 DD 19 46 08 21 C7 AC 90 00 
00 2A 9E 9A 00 
00 36 F6 C6 9F 0D 40 E7 BC 1E 6C 0D 5F 50 00 DF 3C 26 7F D0 2F F3 95 4C C7 FD E6 18 E5 3E 94 82 4A D1 46 02 65 30 E7 1D 29 9D B7 6F 55 9E B8 49 11 63 16 8E C0 CB E8 44 0B 71 31 9F FB D5 2B 6E 70 DE 30 F7 7F C4 E8 57 EC 39 2A BB 4E 02 AD 92 70 5B DE 23 EB 99 AA FA E1 5F 9E 25 39 0A 39 C2 4F 41 87 82 98 6F 26 2E 5A 8E A2 E5 12 8C 70 41 00 9E 46 4D 9B 18 5D 52 7E 77 9B 16 F3 2A BC 2A 11 FB 53 76 81 8F B7 0C 5F BA 2F A0 A9 9A F2 75 45 78 D0 69 83 3D 05 78 32 68 99 8F 9F B9 14 26 6E 05 06 58 13 D4 7E 98 A2 51 02 F4 81 05 0A F0 DB 0E 8B BB DA C8 6C 56 E7 28 80 A3 DC 12 13 62 E0 CB AA 7B 44 0A E4 44 32 3F 33 8F 31 30 44 E2 EB 00 6F BF F0 42 03 4A AD 15 80 76 97 2E B5 14 B6 CA D0 37 3D E0 67 4A AB A0 96 66 59 85 65 F8 11 C6 B4 64 03 0F 65 78 C8 3B B4 00 58 6D 35 F3 90 00

As I understand it I first create a new PDF file with a predefined contents section which contains the certificate and the signature. It takes the digest from the rest of the input PDF and sends it to the smart card to get it hashed. Then that hash along with the appearance and certificate chain is used to do MakeSignature.SignDetached(). I've looked at following post1 and post2 but they do not seem to apply to my case.
<p>I'm trying to implement a PDF signature with a smartcard using iText 5.5.11. The smart card itself is a Mongolian national ID card which itself seems to be a type of Gemalto. I don't have the dll so I've implemented the iExternalSignature with APDU commands. The signed PDF says it's signed by Unknown and error encountered while BER decoding. There's a certificate file already extracted from the smart card and on the computer. SmartCardHandler is a handler for sending and receiving APDU commands.</p>
<p>Here's my SignPdf implementation.</p>
<pre><code> private static void SignPdf(string pdfPath, string signedPdfPath, SmartCardHandler handler, string certificatePath)
{
using (PdfReader reader = new PdfReader(pdfPath))
using (FileStream os = new FileStream(signedPdfPath, FileMode.Create))
{
X509Certificate2 cert = new X509Certificate2(certificatePath);
Org.BouncyCastle.X509.X509Certificate bouncyCert = ConvertToBouncyCastle(cert);
List<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate> { bouncyCert };

PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "reason";
appearance.Location = "location";
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(0, 0, 200, 100), 1, "sig");
appearance.Certificate = chain[0];

IExternalSignature external = new SmartCardSignature(handler);

MakeSignature.SignDetached(appearance, external, chain, null, null, null, 0, CryptoStandard.CMS);
}
}
</code></pre>
<p>and here is my external signature implementation</p>
<pre><code>class SmartCardSignature : IExternalSignature
{
private readonly SmartCardHandler _handler;

public SmartCardSignature(SmartCardHandler handler)
{
_handler = handler;
}

public byte[] Sign(byte[] message)
{
IDigest messageDigest = DigestUtilities.GetDigest(GetHashAlgorithm());
byte[] hash = DigestAlgorithms.Digest(messageDigest, message);

byte[] sendHash = new byte[] { 0x00, 0x2A, 0x90, 0xA0, 0x22, 0x90, 0x20, (byte)hash.Length }.Concat(hash).ToArray();
_handler.SendApduCommand(sendHash);
byte[] getHash = new byte[] { 0x00, 0xC0, 0x00, 0x00, 0x20 };
_handler.SendApduCommand(getHash);
byte[] signApdu = new byte[] { 0x00, 0x2A, 0x9E, 0x9A, 0x00 };
byte[] signatureWith9000 = _handler.SendApduCommand(signApdu);;

if (signatureWith9000.Length < 2 || signatureWith9000[^2] != 0x90 || signatureWith9000[^1] != 0x00)
{
throw new InvalidOperationException("Failed to sign the message using the smart card.");
}

byte[] signature = signatureWith9000.Take(signatureWith9000.Length - 2).ToArray();
return signature;
}

public string GetHashAlgorithm() => "SHA-256";

public string GetEncryptionAlgorithm() => "RSA";
}
</code></pre>
<p><a href="https://drive.google.com/file/d/15Q_P78tppziRcMfDlRP-bKzSTOncRc3V/view?usp=sharing" rel="nofollow noreferrer">here's a test pdf before signing</a></p>
<p><a href="https://drive.google.com/file/d/1K0-51PAx6aD2SIudV0_GFc2-yVyt6oAU/view?usp=sharing" rel="nofollow noreferrer">and here's an example cms signed pdf</a></p>
<p><a href="https://drive.google.com/file/d/1Z4eE1scb68C3FdSqpO_Bk-UFAs4EsoA4/view?usp=sharing" rel="nofollow noreferrer">and here's an example cades (not sure) signed pdf</a></p>
<p>here's the apdu trace, pin code is 1111</p>
<pre><code>00 A4 04 00 0C A0 00 00 00 18 40 00 00 01 63 42 00
90 00
00 20 00 81 08 31 31 31 31 30 30 30 30
90 00
00 22 41 B6 06 84 01 02 80 01 42
90 00
00 2A 90 A0 22 90 20 20 0B 2D C2 F7 37 64 BE 40 F9 F3 4C 33 F9 BA F5 4E 49 06 4D 63 C1 B7 CA 51 DD 19 46 08 21 C7 AC 90
61 20
00 C0 00 00 20
20 0B 2D C2 F7 37 64 BE 40 F9 F3 4C 33 F9 BA F5 4E 49 06 4D 63 C1 B7 CA 51 DD 19 46 08 21 C7 AC 90 00
00 2A 9E 9A 00
00 36 F6 C6 9F 0D 40 E7 BC 1E 6C 0D 5F 50 00 DF 3C 26 7F D0 2F F3 95 4C C7 FD E6 18 E5 3E 94 82 4A D1 46 02 65 30 E7 1D 29 9D B7 6F 55 9E B8 49 11 63 16 8E C0 CB E8 44 0B 71 31 9F FB D5 2B 6E 70 DE 30 F7 7F C4 E8 57 EC 39 2A BB 4E 02 AD 92 70 5B DE 23 EB 99 AA FA E1 5F 9E 25 39 0A 39 C2 4F 41 87 82 98 6F 26 2E 5A 8E A2 E5 12 8C 70 41 00 9E 46 4D 9B 18 5D 52 7E 77 9B 16 F3 2A BC 2A 11 FB 53 76 81 8F B7 0C 5F BA 2F A0 A9 9A F2 75 45 78 D0 69 83 3D 05 78 32 68 99 8F 9F B9 14 26 6E 05 06 58 13 D4 7E 98 A2 51 02 F4 81 05 0A F0 DB 0E 8B BB DA C8 6C 56 E7 28 80 A3 DC 12 13 62 E0 CB AA 7B 44 0A E4 44 32 3F 33 8F 31 30 44 E2 EB 00 6F BF F0 42 03 4A AD 15 80 76 97 2E B5 14 B6 CA D0 37 3D E0 67 4A AB A0 96 66 59 85 65 F8 11 C6 B4 64 03 0F 65 78 C8 3B B4 00 58 6D 35 F3 90 00
</code></pre>
<p>As I understand it I first create a new PDF file with a predefined contents section which contains the certificate and the signature. It takes the digest from the rest of the input PDF and sends it to the smart card to get it hashed. Then that hash along with the appearance and certificate chain is used to do MakeSignature.SignDetached(). I've looked at following <a href="https://stackoverflow.com/questions...-pdf-using-external-signature-with-smart-card">post1</a> and <a href="https://stackoverflow.com/questions/54559547/external-signing-pdf-with-itext">post2</a> but they do not seem to apply to my case.</p>
Continue reading...
 
Top