コード例 #1
0
ファイル: DemoApp.cs プロジェクト: zulkifle/Pkcs11Interop.PDF
        /// <summary>
        /// Main method specifying where program execution is to begin
        /// </summary>
        /// <param name="args">Command line arguments passed to the program</param>
        static void Main(string[] args)
        {
            try
            {
                // Parse command line arguments
                string pkcs11Library = null;
                int    listTokens    = 0;
                int    listObjects   = 0;
                int    sign          = 0;
                string tokenSerial   = null;
                string tokenLabel    = null;
                string pin           = null;
                string keyLabel      = null;
                string keyId         = null;
                string inputPdf      = null;
                string outputPdf     = null;
                string hashAlg       = null;
                string certsDir      = null;

                if (args.Length == 0)
                {
                    ExitWithHelp(null);
                }

                int i = 0;
                while (i < args.Length)
                {
                    switch (args[i])
                    {
                    case _argPkcs11Library:
                        pkcs11Library = args[++i];
                        break;

                    case _argListTokens:
                        listTokens = 1;
                        break;

                    case _argListObjects:
                        listObjects = 1;
                        break;

                    case _argSign:
                        sign = 1;
                        break;

                    case _argTokenSerial:
                        tokenSerial = args[++i];
                        break;

                    case _argTokenLabel:
                        tokenLabel = args[++i];
                        break;

                    case _argPin:
                        pin = args[++i];
                        break;

                    case _argKeyLabel:
                        keyLabel = args[++i];
                        break;

                    case _argKeyId:
                        keyId = args[++i];
                        break;

                    case _argInputPdf:
                        inputPdf = args[++i];
                        break;

                    case _argOutputPdf:
                        outputPdf = args[++i];
                        break;

                    case _argHashAlg:
                        hashAlg = args[++i];
                        break;

                    case _argCertsDir:
                        certsDir = args[++i];
                        break;

                    default:
                        ExitWithHelp("Invalid argument: " + args[i]);
                        break;
                    }

                    i++;
                }

                // Validate operation modes
                if (listTokens + listObjects + sign != 1)
                {
                    ExitWithHelp(string.Format("Argument \"{0}\", \"{1}\" or \"{2}\" has to be specified", _argListTokens, _argListObjects, _argSign));
                }

                // Handle "--list-tokens" operation mode
                if (listTokens == 1)
                {
                    // Validate command line arguments
                    if (string.IsNullOrEmpty(pkcs11Library))
                    {
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    }
                    if (!string.IsNullOrEmpty(tokenSerial))
                    {
                        ExitWithHelp("Unexpected argument: " + _argTokenSerial);
                    }
                    if (!string.IsNullOrEmpty(tokenLabel))
                    {
                        ExitWithHelp("Unexpected argument: " + _argTokenLabel);
                    }
                    if (!string.IsNullOrEmpty(pin))
                    {
                        ExitWithHelp("Unexpected argument: " + _argPin);
                    }
                    if (!string.IsNullOrEmpty(keyLabel))
                    {
                        ExitWithHelp("Unexpected argument: " + _argKeyLabel);
                    }
                    if (!string.IsNullOrEmpty(keyId))
                    {
                        ExitWithHelp("Unexpected argument: " + _argKeyId);
                    }
                    if (!string.IsNullOrEmpty(inputPdf))
                    {
                        ExitWithHelp("Unexpected argument: " + _argInputPdf);
                    }
                    if (!string.IsNullOrEmpty(outputPdf))
                    {
                        ExitWithHelp("Unexpected argument: " + _argOutputPdf);
                    }
                    if (!string.IsNullOrEmpty(hashAlg))
                    {
                        ExitWithHelp("Unexpected argument: " + _argHashAlg);
                    }
                    if (!string.IsNullOrEmpty(certsDir))
                    {
                        ExitWithHelp("Unexpected argument: " + _argCertsDir);
                    }

                    // Perform requested operation
                    using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library))
                    {
                        Console.WriteLine("Listing available tokens");

                        int          j      = 1;
                        List <Token> tokens = pkcs11Explorer.GetTokens();
                        foreach (Token token in tokens)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Token no." + j);
                            Console.WriteLine("  Manufacturer:       " + token.ManufacturerId);
                            Console.WriteLine("  Model:              " + token.Model);
                            Console.WriteLine("  Serial number:      " + token.SerialNumber);
                            Console.WriteLine("  Label:              " + token.Label);
                            j++;
                        }
                    }
                }

                // Handle "--list-objects" operation mode
                if (listObjects == 1)
                {
                    // Validate command line arguments
                    if (string.IsNullOrEmpty(pkcs11Library))
                    {
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    }
                    if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel))
                    {
                        ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel);
                    }
                    if (string.IsNullOrEmpty(pin))
                    {
                        ExitWithHelp("Required argument: " + _argPin);
                    }
                    if (!string.IsNullOrEmpty(keyLabel))
                    {
                        ExitWithHelp("Unexpected argument: " + _argKeyLabel);
                    }
                    if (!string.IsNullOrEmpty(keyId))
                    {
                        ExitWithHelp("Unexpected argument: " + _argKeyId);
                    }
                    if (!string.IsNullOrEmpty(inputPdf))
                    {
                        ExitWithHelp("Unexpected argument: " + _argInputPdf);
                    }
                    if (!string.IsNullOrEmpty(outputPdf))
                    {
                        ExitWithHelp("Unexpected argument: " + _argOutputPdf);
                    }
                    if (!string.IsNullOrEmpty(hashAlg))
                    {
                        ExitWithHelp("Unexpected argument: " + _argHashAlg);
                    }
                    if (!string.IsNullOrEmpty(certsDir))
                    {
                        ExitWithHelp("Unexpected argument: " + _argCertsDir);
                    }

                    // Perform requested operation
                    using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library))
                    {
                        Console.WriteLine(string.Format("Listing objects available on token with serial \"{0}\" and label \"{1}\"", tokenSerial, tokenLabel));

                        // Find requested token
                        Token foundToken = null;

                        List <Token> tokens = pkcs11Explorer.GetTokens();
                        foreach (Token token in tokens)
                        {
                            if (!string.IsNullOrEmpty(tokenLabel))
                            {
                                if (0 != String.Compare(tokenLabel, token.Label, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    continue;
                                }
                            }

                            if (!string.IsNullOrEmpty(tokenSerial))
                            {
                                if (0 != String.Compare(tokenSerial, token.SerialNumber, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    continue;
                                }
                            }

                            foundToken = token;
                            break;
                        }

                        if (foundToken == null)
                        {
                            throw new TokenNotFoundException(string.Format("Token with serial \"{0}\" and label \"{1}\" was not found", tokenSerial, tokenLabel));
                        }

                        // Get private keys and certificates stored in requested token
                        List <PrivateKey>  privateKeys  = null;
                        List <Certificate> certificates = null;
                        pkcs11Explorer.GetTokenObjects(foundToken, true, pin, out privateKeys, out certificates);

                        // Print private keys
                        int j = 1;
                        foreach (PrivateKey privateKey in privateKeys)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Private key #" + j);

                            int[] matchingCertIds = GetMatchingCertIds(privateKey, certificates);
                            Console.WriteLine("  Matching certs:     " + PrintMatchingIds(matchingCertIds));

                            Console.WriteLine("  ID (CKA_ID):        " + privateKey.Id);
                            Console.WriteLine("  Label (CKA_LABEL):  " + privateKey.Label);

                            // Print public part of RSA key
                            if ((privateKey.PublicKey != null) && (privateKey.PublicKey is RsaKeyParameters))
                            {
                                RsaKeyParameters rsa = privateKey.PublicKey as RsaKeyParameters;
                                Console.WriteLine("  RSA exponent:       " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
                                Console.WriteLine("  RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
                            }

                            j++;
                        }

                        // Print certificates
                        int k = 1;
                        foreach (Certificate certificate in certificates)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Certificate #" + k);

                            int[] matchingKeyIds = GetMatchingKeyIds(certificate, privateKeys);
                            Console.WriteLine("  Matching keys:      " + PrintMatchingIds(matchingKeyIds));

                            X509Certificate2 x509Cert = CertUtils.ToDotNetObject(certificate.Data);

                            Console.WriteLine("  ID (CKA_ID):        " + certificate.Id);
                            Console.WriteLine("  Label (CKA_LABEL):  " + certificate.Label);
                            Console.WriteLine("  Serial number:      " + x509Cert.SerialNumber);
                            Console.WriteLine("  Subject DN:         " + x509Cert.Subject);
                            Console.WriteLine("  Issuer DN:          " + x509Cert.Issuer);
                            Console.WriteLine("  Not before:         " + x509Cert.NotBefore);
                            Console.WriteLine("  Not after:          " + x509Cert.NotAfter);

                            // Print certified public RSA key
                            if ((certificate.PublicKey != null) && (certificate.PublicKey is RsaKeyParameters))
                            {
                                RsaKeyParameters rsa = certificate.PublicKey as RsaKeyParameters;
                                Console.WriteLine("  RSA exponent:       " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
                                Console.WriteLine("  RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
                            }

                            k++;
                        }
                    }
                }

                // Handle "--sign" operation mode
                if (sign == 1)
                {
                    // Use SHA256 as default hashing algorithm
                    HashAlgorithm hashAlgorithm = HashAlgorithm.SHA256;

                    // Validate command line arguments (_argHashAlg and _argCertsDir are optional)
                    if (string.IsNullOrEmpty(pkcs11Library))
                    {
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    }
                    if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel))
                    {
                        ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel);
                    }
                    if (string.IsNullOrEmpty(pin))
                    {
                        ExitWithHelp("Required argument: " + _argPin);
                    }
                    if (string.IsNullOrEmpty(keyLabel) && string.IsNullOrEmpty(keyId))
                    {
                        ExitWithHelp("Required argument: " + _argKeyLabel + " and/or " + _argKeyId);
                    }
                    if (string.IsNullOrEmpty(inputPdf))
                    {
                        ExitWithHelp("Required argument: " + _argInputPdf);
                    }
                    if (string.IsNullOrEmpty(outputPdf))
                    {
                        ExitWithHelp("Required argument: " + _argOutputPdf);
                    }
                    if (!string.IsNullOrEmpty(hashAlg))
                    {
                        hashAlgorithm = (HashAlgorithm)Enum.Parse(typeof(HashAlgorithm), hashAlg);
                    }

                    // Perform requested operation
                    using (Pkcs11RsaSignature pkcs11RsaSignature = new Pkcs11RsaSignature(pkcs11Library, tokenSerial, tokenLabel, pin, keyLabel, keyId, hashAlgorithm))
                    {
                        Console.WriteLine(string.Format("Signing PDF document \"{0}\" using private key with ID \"{1}\" and label \"{2}\" stored on token with serial \"{3}\" and label \"{4}\"", inputPdf, keyId, keyLabel, tokenSerial, tokenLabel));

                        // Read signing certificate from the token
                        byte[] signingCertificate = pkcs11RsaSignature.GetSigningCertificate();

                        // Read all certificates stored on the token
                        List <byte[]> otherCertificates = pkcs11RsaSignature.GetAllCertificates();

                        // Read additional certificates from directory
                        if (!string.IsNullOrEmpty(certsDir))
                        {
                            foreach (string file in Directory.GetFiles(certsDir))
                            {
                                otherCertificates.Add(File.ReadAllBytes(file));
                            }
                        }

                        // Build certification path for the signing certificate
                        ICollection <Org.BouncyCastle.X509.X509Certificate> certPath = CertUtils.BuildCertPath(signingCertificate, otherCertificates);

                        // Read unsigned PDF document
                        using (PdfReader pdfReader = new PdfReader(inputPdf))
                        {
                            // Create output stream for signed PDF document
                            using (FileStream outputStream = new FileStream(outputPdf, FileMode.Create))
                            {
                                // Create PdfStamper that applies extra content to the PDF document
                                using (PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, outputStream, '\0', Path.GetTempFileName(), true))
                                {
                                    // Sign PDF document
                                    MakeSignature.SignDetached(pdfStamper.SignatureAppearance, pkcs11RsaSignature, certPath, null, null, null, 0, CryptoStandard.CADES);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(@"Operation error: " + ex.GetType() + " - " + ex.Message);
                Console.WriteLine(ex.StackTrace);
                Environment.Exit(_exitError);
            }

            Environment.Exit(_exitSuccess);
        }
コード例 #2
0
ファイル: DemoApp.cs プロジェクト: jariq/Pkcs11Interop.PDF
        /// <summary>
        /// Main method specifying where program execution is to begin
        /// </summary>
        /// <param name="args">Command line arguments passed to the program</param>
        static void Main(string[] args)
        {
            try
            {
                // Parse command line arguments
                string pkcs11Library = null;
                int listTokens = 0;
                int listObjects = 0;
                int sign = 0;
                string tokenSerial = null;
                string tokenLabel = null;
                string pin = null;
                string keyLabel = null;
                string keyId = null;
                string inputPdf = null;
                string outputPdf = null;
                string hashAlg = null;
                string certsDir = null;

                if (args.Length == 0)
                    ExitWithHelp(null);

                int i = 0;
                while (i < args.Length)
                {
                    switch (args[i])
                    {
                        case _argPkcs11Library:
                            pkcs11Library = args[++i];
                            break;
                        case _argListTokens:
                            listTokens = 1;
                            break;
                        case _argListObjects:
                            listObjects = 1;
                            break;
                        case _argSign:
                            sign = 1;
                            break;
                        case _argTokenSerial:
                            tokenSerial = args[++i];
                            break;
                        case _argTokenLabel:
                            tokenLabel = args[++i];
                            break;
                        case _argPin:
                            pin = args[++i];
                            break;
                        case _argKeyLabel:
                            keyLabel = args[++i];
                            break;
                        case _argKeyId:
                            keyId = args[++i];
                            break;
                        case _argInputPdf:
                            inputPdf = args[++i];
                            break;
                        case _argOutputPdf:
                            outputPdf = args[++i];
                            break;
                        case _argHashAlg:
                            hashAlg = args[++i];
                            break;
                        case _argCertsDir:
                            certsDir = args[++i];
                            break;
                        default:
                            ExitWithHelp("Invalid argument: " + args[i]);
                            break;
                    }

                    i++;
                }

                // Validate operation modes
                if (listTokens + listObjects + sign != 1)
                    ExitWithHelp(string.Format("Argument \"{0}\", \"{1}\" or \"{2}\" has to be specified", _argListTokens, _argListObjects, _argSign));

                // Handle "--list-tokens" operation mode
                if (listTokens == 1)
                {
                    // Validate command line arguments
                    if (string.IsNullOrEmpty(pkcs11Library))
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    if (!string.IsNullOrEmpty(tokenSerial))
                        ExitWithHelp("Unexpected argument: " + _argTokenSerial);
                    if (!string.IsNullOrEmpty(tokenLabel))
                        ExitWithHelp("Unexpected argument: " + _argTokenLabel);
                    if (!string.IsNullOrEmpty(pin))
                        ExitWithHelp("Unexpected argument: " + _argPin);
                    if (!string.IsNullOrEmpty(keyLabel))
                        ExitWithHelp("Unexpected argument: " + _argKeyLabel);
                    if (!string.IsNullOrEmpty(keyId))
                        ExitWithHelp("Unexpected argument: " + _argKeyId);
                    if (!string.IsNullOrEmpty(inputPdf))
                        ExitWithHelp("Unexpected argument: " + _argInputPdf);
                    if (!string.IsNullOrEmpty(outputPdf))
                        ExitWithHelp("Unexpected argument: " + _argOutputPdf);
                    if (!string.IsNullOrEmpty(hashAlg))
                        ExitWithHelp("Unexpected argument: " + _argHashAlg);
                    if (!string.IsNullOrEmpty(certsDir))
                        ExitWithHelp("Unexpected argument: " + _argCertsDir);

                    // Perform requested operation
                    using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library))
                    {
                        Console.WriteLine("Listing available tokens");

                        int j = 1;
                        List<Token> tokens = pkcs11Explorer.GetTokens();
                        foreach (Token token in tokens)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Token no." + j);
                            Console.WriteLine("  Manufacturer:       " + token.ManufacturerId);
                            Console.WriteLine("  Model:              " + token.Model);
                            Console.WriteLine("  Serial number:      " + token.SerialNumber);
                            Console.WriteLine("  Label:              " + token.Label);
                            j++;
                        }
                    }
                }

                // Handle "--list-objects" operation mode
                if (listObjects == 1)
                {
                    // Validate command line arguments
                    if (string.IsNullOrEmpty(pkcs11Library))
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel))
                        ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel);
                    if (string.IsNullOrEmpty(pin))
                        ExitWithHelp("Required argument: " + _argPin);
                    if (!string.IsNullOrEmpty(keyLabel))
                        ExitWithHelp("Unexpected argument: " + _argKeyLabel);
                    if (!string.IsNullOrEmpty(keyId))
                        ExitWithHelp("Unexpected argument: " + _argKeyId);
                    if (!string.IsNullOrEmpty(inputPdf))
                        ExitWithHelp("Unexpected argument: " + _argInputPdf);
                    if (!string.IsNullOrEmpty(outputPdf))
                        ExitWithHelp("Unexpected argument: " + _argOutputPdf);
                    if (!string.IsNullOrEmpty(hashAlg))
                        ExitWithHelp("Unexpected argument: " + _argHashAlg);
                    if (!string.IsNullOrEmpty(certsDir))
                        ExitWithHelp("Unexpected argument: " + _argCertsDir);

                    // Perform requested operation
                    using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library))
                    {
                        Console.WriteLine(string.Format("Listing objects available on token with serial \"{0}\" and label \"{1}\"", tokenSerial, tokenLabel));

                        // Find requested token
                        Token foundToken = null;

                        List<Token> tokens = pkcs11Explorer.GetTokens();
                        foreach (Token token in tokens)
                        {
                            if (!string.IsNullOrEmpty(tokenLabel))
                                if (0 != String.Compare(tokenLabel, token.Label, StringComparison.InvariantCultureIgnoreCase))
                                    continue;

                            if (!string.IsNullOrEmpty(tokenSerial))
                                if (0 != String.Compare(tokenSerial, token.SerialNumber, StringComparison.InvariantCultureIgnoreCase))
                                    continue;

                            foundToken = token;
                            break;
                        }

                        if (foundToken == null)
                            throw new TokenNotFoundException(string.Format("Token with serial \"{0}\" and label \"{1}\" was not found", tokenSerial, tokenLabel));

                        // Get private keys and certificates stored in requested token
                        List<PrivateKey> privateKeys = null;
                        List<Certificate> certificates = null;
                        pkcs11Explorer.GetTokenObjects(foundToken, true, pin, out privateKeys, out certificates);

                        // Print private keys
                        int j = 1;
                        foreach (PrivateKey privateKey in privateKeys)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Private key #" + j);

                            int[] matchingCertIds = GetMatchingCertIds(privateKey, certificates);
                            Console.WriteLine("  Matching certs:     " + PrintMatchingIds(matchingCertIds));

                            Console.WriteLine("  ID (CKA_ID):        " + privateKey.Id);
                            Console.WriteLine("  Label (CKA_LABEL):  " + privateKey.Label);

                            // Print public part of RSA key
                            if ((privateKey.PublicKey != null) && (privateKey.PublicKey is RsaKeyParameters))
                            {
                                RsaKeyParameters rsa = privateKey.PublicKey as RsaKeyParameters;
                                Console.WriteLine("  RSA exponent:       " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
                                Console.WriteLine("  RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
                            }

                            j++;
                        }

                        // Print certificates
                        int k = 1;
                        foreach (Certificate certificate in certificates)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Certificate #" + k);

                            int[] matchingKeyIds = GetMatchingKeyIds(certificate, privateKeys);
                            Console.WriteLine("  Matching keys:      " + PrintMatchingIds(matchingKeyIds));

                            X509Certificate2 x509Cert = CertUtils.ToDotNetObject(certificate.Data);

                            Console.WriteLine("  ID (CKA_ID):        " + certificate.Id);
                            Console.WriteLine("  Label (CKA_LABEL):  " + certificate.Label);
                            Console.WriteLine("  Serial number:      " + x509Cert.SerialNumber);
                            Console.WriteLine("  Subject DN:         " + x509Cert.Subject);
                            Console.WriteLine("  Issuer DN:          " + x509Cert.Issuer);
                            Console.WriteLine("  Not before:         " + x509Cert.NotBefore);
                            Console.WriteLine("  Not after:          " + x509Cert.NotAfter);

                            // Print certified public RSA key
                            if ((certificate.PublicKey != null) && (certificate.PublicKey is RsaKeyParameters))
                            {
                                RsaKeyParameters rsa = certificate.PublicKey as RsaKeyParameters;
                                Console.WriteLine("  RSA exponent:       " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
                                Console.WriteLine("  RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
                            }

                            k++;
                        }
                    }
                }

                // Handle "--sign" operation mode
                if (sign == 1)
                {
                    // Use SHA256 as default hashing algorithm
                    HashAlgorithm hashAlgorithm = HashAlgorithm.SHA256;

                    // Validate command line arguments (_argHashAlg and _argCertsDir are optional)
                    if (string.IsNullOrEmpty(pkcs11Library))
                        ExitWithHelp("Required argument: " + _argPkcs11Library);
                    if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel))
                        ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel);
                    if (string.IsNullOrEmpty(pin))
                        ExitWithHelp("Required argument: " + _argPin);
                    if (string.IsNullOrEmpty(keyLabel) && string.IsNullOrEmpty(keyId))
                        ExitWithHelp("Required argument: " + _argKeyLabel + " and/or " + _argKeyId);
                    if (string.IsNullOrEmpty(inputPdf))
                        ExitWithHelp("Required argument: " + _argInputPdf);
                    if (string.IsNullOrEmpty(outputPdf))
                        ExitWithHelp("Required argument: " + _argOutputPdf);
                    if (!string.IsNullOrEmpty(hashAlg))
                        hashAlgorithm = (HashAlgorithm)Enum.Parse(typeof(HashAlgorithm), hashAlg);

                    // Perform requested operation
                    using (Pkcs11RsaSignature pkcs11RsaSignature = new Pkcs11RsaSignature(pkcs11Library, tokenSerial, tokenLabel, pin, keyLabel, keyId, hashAlgorithm))
                    {
                        Console.WriteLine(string.Format("Signing PDF document \"{0}\" using private key with ID \"{1}\" and label \"{2}\" stored on token with serial \"{3}\" and label \"{4}\"", inputPdf, keyId, keyLabel, tokenSerial, tokenLabel));

                        // Read signing certificate from the token
                        byte[] signingCertificate = pkcs11RsaSignature.GetSigningCertificate();

                        // Read all certificates stored on the token
                        List<byte[]> otherCertificates = pkcs11RsaSignature.GetAllCertificates();

                        // Read additional certificates from directory
                        if (!string.IsNullOrEmpty(certsDir))
                            foreach (string file in Directory.GetFiles(certsDir))
                                otherCertificates.Add(File.ReadAllBytes(file));

                        // Build certification path for the signing certificate
                        ICollection<Org.BouncyCastle.X509.X509Certificate> certPath = CertUtils.BuildCertPath(signingCertificate, otherCertificates);

                        // Read unsigned PDF document
                        using (PdfReader pdfReader = new PdfReader(inputPdf))
                        {
                            // Create output stream for signed PDF document
                            using (FileStream outputStream = new FileStream(outputPdf, FileMode.Create))
                            {
                                // Create PdfStamper that applies extra content to the PDF document
                                using (PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, outputStream, '\0', Path.GetTempFileName(), true))
                                {
                                    // Sign PDF document
                                    MakeSignature.SignDetached(pdfStamper.SignatureAppearance, pkcs11RsaSignature, certPath, null, null, null, 0, CryptoStandard.CADES);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(@"Operation error: " + ex.GetType() + " - " + ex.Message);
                Console.WriteLine(ex.StackTrace);
                Environment.Exit(_exitError);
            }

            Environment.Exit(_exitSuccess);
        }