public ActionResult Index(string userfile)
        {
            // Our action only works if a userfile is given to work with
            if (string.IsNullOrEmpty(userfile)) {
                return HttpNotFound();
            }
            var filename = userfile.Replace("_", "."); // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC

            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient()) {
                Validate = true // Specify that we want to validate the signatures in the file, not only inspect them
            };

            // Set the PDF file
            sigExplorer.SetSignatureFile(Server.MapPath("~/App_Data/" + filename));

            // Parameters for the signature validation. We have encapsulated this code in a method to include several
            // possibilities depending on the argument passed. Experiment changing the argument to see different validation
            // configurations. Once you decide which is best for your case, you can place the code directly here.
            setValidationParameters(sigExplorer, 1);
            // try changing this number ---------^ for different validation parameters

            // Call the Open() method, which returns the signature file's information
            var signature = sigExplorer.Open();

            // Render the information (see file Views/OpenPadesSignature/Index.html for more information on the information returned)
            return View(signature);
        }
        public ActionResult Index(string userfile)
        {
            // Our action only works if a userfile is given to work with
            if (string.IsNullOrEmpty(userfile))
            {
                return(HttpNotFound());
            }
            var filename = userfile.Replace("_", ".");             // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC

            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                Validate = true                 // Specify that we want to validate the signatures in the file, not only inspect them
            };

            // Set the PDF file
            sigExplorer.SetSignatureFile(Server.MapPath("~/App_Data/" + filename));

            // Parameters for the signature validation. We have encapsulated this code in a method to include several
            // possibilities depending on the argument passed. Experiment changing the argument to see different validation
            // configurations. Once you decide which is best for your case, you can place the code directly here.
            setValidationParameters(sigExplorer, 1);
            // try changing this number ---------^ for different validation parameters

            // Call the Open() method, which returns the signature file's information
            var signature = sigExplorer.Open();

            // Render the information (see file Views/OpenPadesSignature/Index.html for more information on the information returned)
            return(View(signature));
        }
Example #3
0
        public ActionResult Index(string userfile)
        {
            // Our action only works if a userfile is given to work with.
            if (string.IsNullOrEmpty(userfile))
            {
                return(HttpNotFound());
            }
            var filename = userfile.Replace("_", ".");
            // Note: we're receiving the userfile argument with "_" as "." because of limitations of
            // ASP.NET MVC.

            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures.
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want to validate the signatures in the file, not only inspect them.
                Validate = true,
                // Specify the parameters for the signature validation:
                // Accept any PAdES signature as long as the signer has an ICP-Brasil certificate.
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                // We have encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId()
            };

            // Set the PDF file
            sigExplorer.SetSignatureFile(Server.MapPath("~/App_Data/" + filename));

            // Call the Open() method, which returns the signature file's information
            var signature = sigExplorer.Open();

            // Render the information (see file Views/OpenPadesSignature/Index.html for more information on
            // the information returned)
            return(View(signature));
        }
Example #4
0
        public async Task <ActionResult> Index(string userfile)
        {
            // Our action only works if a userfile is given to work with.
            if (!StorageMock.TryGetFile(userfile, out string userfilePath))
            {
                return(HttpNotFound());
            }

            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures.
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want to validate the signatures in the file, not only inspect them.
                Validate = true,
                // Specify the parameters for the signature validation:
                // Accept any PAdES signature as long as the signer has an ICP-Brasil certificate.
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                // Specify the security context to be used to determine trust in the certificate chain. We
                // have encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId()
            };

            // Set the PAdES signature file.
            sigExplorer.SetSignatureFile(userfilePath);

            // Call the Open() method, which returns the signature file's information.
            var signature = await sigExplorer.OpenAsync();

            // Render the information (see file OpenPadesSignature/Index.html for more information on
            // the information returned).
            return(View(new OpenPadesSignatureModel()
            {
                Signature = signature
            }));
        }
Example #5
0
        public async Task <ActionResult> Index(string userfile)
        {
            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures.
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want an audit package to be generated, and that the signed file should be
                // included in the package.
                GenerateAuditPackage            = true,
                IncludeSignedFileInAuditPackage = true,
                // In order to generate an audit package, we must also pass Validate = true.
                Validate = true,
                // Specify the parameters for the signature validation:
                // Accept any PAdES signature as long as the signer has an ICP-Brasil certificate.
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                // We have encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId()
            };

            // Set the PDF file.
            if (string.IsNullOrEmpty(userfile))
            {
                // If no file is passed, we use a previously signed and B-Stamped file.
                sigExplorer.SetSignatureFile(Server.MapPath("~/Content/bstamped.pdf"));
            }
            else
            {
                sigExplorer.SetSignatureFile(Server.MapPath("~/App_Data/" + userfile.Replace("_", ".")));
                // Note: we're receiving the userfile argument with "_" as "." because of limitations of
                // ASP.NET MVC.
            }

            // Call the OpenAsync() method, which returns the signature file's information.
            var signature = await sigExplorer.OpenAsync();

            // If the document has been B-Stamped, store the "digest index file" to show a link on the page.
            if (signature.BStamp != null)
            {
                string indexFileId;
                using (var indexFileStream = signature.BStamp.IndexFile.OpenRead()) {
                    indexFileId = StorageMock.Store(indexFileStream, ".txt");
                }
                ViewBag.BStampIndexFile = indexFileId;
            }

            // Store the generated audit package. Notice that although we asked for its generation, the
            // signature might not have been B-Stamped yet, so an audit package might not be returned.
            if (signature.AuditPackage != null)
            {
                string auditPkgId;
                using (var auditPkgStream = signature.AuditPackage.OpenRead()) {
                    auditPkgId = StorageMock.Store(auditPkgStream, ".zip");
                }
                ViewBag.AuditPackageFile = auditPkgId;
            }

            // Render the information. (see file Views/OpenPadesSignatureBStamp/Index.html for more
            // information on the information returned)
            return(View(signature));
        }
        // This function is called by the Index method (see above). It contains examples of signature validation parameters.
        private static void setValidationParameters(PadesSignatureExplorer sigExplorer, int caseNumber)
        {
            switch (caseNumber)
            {
            /*
             *      Example #1: accept any PAdES signature as long as the signer has an ICP-Brasil certificate (RECOMMENDED)
             *
             *      These parameters will only accept signatures made with ICP-Brasil certificates that comply with the
             *      minimal security features defined in the PAdES standard (ETSI TS 102 778). The signatures need not, however,
             *      follow the extra requirements defined in the ICP-Brasil signature policy documentation (DOC-ICP-15.03).
             *
             *      These are the recommended parameters for ICP-Brasil, since the PAdES policies, released on 2016-06-01,
             *      are still in adoption phase by most implementors.
             */
            case 1:
                // By omitting the accepted policies catalog and defining a default policy, we're telling Rest PKI to validate
                // all signatures in the file with the default policy -- even signatures with an explicit signature policy.
                sigExplorer.AcceptableExplicitPolicies = null;
                sigExplorer.DefaultSignaturePolicyId   = StandardPadesSignaturePolicies.Basic;
                // The PAdES Basic policy requires us to choose a security context
                sigExplorer.SecurityContextId = StandardSecurityContexts.PkiBrazil;
                break;


            /*
             *      Example #2: accept only 100%-compliant ICP-Brasil signatures
             */
            case 2:
                // By specifying a catalog of acceptable policies and omitting the default signature policy, we're telling Rest PKI
                // that only the policies in the catalog should be accepted
                sigExplorer.AcceptableExplicitPolicies = SignaturePolicyCatalog.GetPkiBrazilPades();
                sigExplorer.DefaultSignaturePolicyId   = null;
                break;


            /*
             *      Example #3: accept any PAdES signature as long as the signer is trusted by Windows
             *
             *      Same case as example #1, but using the WindowsServer trust arbitrator
             */
            case 3:
                sigExplorer.AcceptableExplicitPolicies = null;
                sigExplorer.DefaultSignaturePolicyId   = StandardPadesSignaturePolicies.Basic;
                sigExplorer.SecurityContextId          = StandardSecurityContexts.WindowsServer;
                break;

            /*
             *      Example #4: accept only 100%-compliant ICP-Brasil signatures that provide signer certificate protection.
             *
             *      "Signer certificate protection" means that a signature keeps its validity even after the signer certificate
             *      is revoked or expires. On ICP-Brasil, this translates to policies AD-RT and up (not AD-RB).
             */
            case 4:
                sigExplorer.AcceptableExplicitPolicies = SignaturePolicyCatalog.GetPkiBrazilPadesWithSignerCertificateProtection();
                sigExplorer.DefaultSignaturePolicyId   = null;
                break;
            }
        }
        // This function is called by the Index method (see above). It contains examples of signature validation parameters.
        private static void setValidationParameters(PadesSignatureExplorer sigExplorer, int caseNumber)
        {
            switch (caseNumber) {

                /*
                    Example #1: accept any PAdES signature as long as the signer has an ICP-Brasil certificate (RECOMMENDED)

                    These parameters will only accept signatures made with ICP-Brasil certificates that comply with the
                    minimal security features defined in the PAdES standard (ETSI TS 102 778). The signatures need not, however,
                    follow the extra requirements defined in the ICP-Brasil signature policy documentation (DOC-ICP-15.03).

                    These are the recommended parameters for ICP-Brasil, since the PAdES policies, released on 2016-06-01,
                    are still in adoption phase by most implementors.
                 */
                case 1:
                    // By omitting the accepted policies catalog and defining a default policy, we're telling Rest PKI to validate
                    // all signatures in the file with the default policy -- even signatures with an explicit signature policy.
                    sigExplorer.AcceptableExplicitPolicies = null;
                    sigExplorer.DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic;
                    // The PAdES Basic policy requires us to choose a security context
                    sigExplorer.SecurityContextId = StandardSecurityContexts.PkiBrazil;
                    break;

                /*
                    Example #2: accept only 100%-compliant ICP-Brasil signatures
                 */
                case 2:
                    // By specifying a catalog of acceptable policies and omitting the default signature policy, we're telling Rest PKI
                    // that only the policies in the catalog should be accepted
                    sigExplorer.AcceptableExplicitPolicies = SignaturePolicyCatalog.GetPkiBrazilPades();
                    sigExplorer.DefaultSignaturePolicyId = null;
                    break;

                /*
                    Example #3: accept any PAdES signature as long as the signer is trusted by Windows

                    Same case as example #1, but using the WindowsServer trust arbitrator
                 */
                case 3:
                    sigExplorer.AcceptableExplicitPolicies = null;
                    sigExplorer.DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic;
                    sigExplorer.SecurityContextId = StandardSecurityContexts.WindowsServer;
                    break;

                /*
                    Example #4: accept only 100%-compliant ICP-Brasil signatures that provide signer certificate protection.

                    "Signer certificate protection" means that a signature keeps its validity even after the signer certificate
                    is revoked or expires. On ICP-Brasil, this translates to policies AD-RT and up (not AD-RB).
                 */
                case 4:
                    sigExplorer.AcceptableExplicitPolicies = SignaturePolicyCatalog.GetPkiBrazilPadesWithSignerCertificateProtection();
                    sigExplorer.DefaultSignaturePolicyId = null;
                    break;
            }
        }
Example #8
0
        // GET: CheckPadesRest?c={id}
        public ActionResult Index(string c)
        {
            // On PrinterFriendlyVersionController, we stored the unformatted version of the verification
            // code (without hyphens) but used the formatted version (with hiphens) on the printer-friendly
            // PDF. Now, we remove the hyphens before looking it up.
            var verificationCode = AlphaCode.Parse(c);

            // Get document associated with verification code.
            var fileId = StorageMock.LookupVerificationCode(verificationCode);

            if (fileId == null)
            {
                // Invalid code give!
                // Small delay to slow down brute-force attacks (if you want to be extra careful you might
                // want to add a CAPTCHA to the process).
                Thread.Sleep(TimeSpan.FromSeconds(2));
                // Return Not Found
                return(HttpNotFound());
            }

            // Read document from storage.
            var fileContent = StorageMock.Read(fileId);

            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures.
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want to validate the signatures in the file, not only inspect them.
                Validate = true,
                // Specify the parameters for the signature validation:
                // Accept any PAdES signature as long as the signer has an ICP-Brasil certificate.
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                // Specify the security context to be used to determine trust in the certificate chain. We
                // have encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId()
            };

            // Set the PDF file.
            sigExplorer.SetSignatureFile(fileContent);

            // Call the Open() method, which returns the signature file's information.
            var signature = sigExplorer.Open();

            // Render the information (see file Check/Index.html for more information on
            // the information returned).
            return(View(new OpenPadesSignatureModel()
            {
                Signature = signature,
                File = fileId
            }));
        }
Example #9
0
        protected void Page_Load(object sender, EventArgs e)
        {
            // Get verification code from query string
            var formattedVerificationCode = Request.QueryString["code"];

            // On PrinterFriendlyVersion.aspx, we stored the unformatted version of the verification code (without hyphens) but
            // used the formatted version (with hyphens) on the printer-friendly PDF. Now, we remove the hyphens before looking it up.
            var verificationCode = AlphaCode.Parse(formattedVerificationCode);

            // Get document associated with verification code
            var fileId = StorageMock.LookupVerificationCode(verificationCode);

            if (fileId == null)
            {
                // Invalid code given!
                // Small delay to slow down brute-force attacks (if you want to be extra careful you might want to add a CAPTCHA to the process)
                Thread.Sleep(TimeSpan.FromSeconds(2));
                // Return Not Found
                Response.StatusCode = 404;
                Response.End();
                return;
            }

            // Read document from storage
            var fileContent = StorageMock.Read(fileId);

            // Open and validate signatures with Rest PKI
            var client      = Util.GetRestPkiClient();
            var sigExplorer = new PadesSignatureExplorer(client)
            {
                Validate = true,
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                SecurityContextId        = Util.GetSecurityContextId(),
            };

            sigExplorer.SetSignatureFile(fileContent);
            var signature = sigExplorer.Open();

            // Set properties for rendering on page (see aspx file)
            this.FileId = fileId;
            this.Model  = signature;
        }
        private byte[] generatePrinterFriendlyVersion(byte[] pdfContent, string verificationCode)
        {
            var client = Util.GetRestPkiClient();

            // The verification code is generated without hyphens to save storage space and avoid
            // copy-and-paste problems. On the PDF generation, we use the "formatted" version, with hyphens
            // (which will later be discarded on the verification page).
            var formattedVerificationCode = Util.FormatVerificationCode(verificationCode);

            // Build the verification link from the constant "VerificationLinkFormat" (see above) and the
            // formatted verification code.
            var verificationLink = string.Format(VerificationLinkFormat, formattedVerificationCode);

            // 1. Upload the PDF
            var blob = client.UploadFile(pdfContent);

            // 2. Inspect signatures on the uploaded PDF
            var sigExplorer = new PadesSignatureExplorer(client)
            {
                Validate = true,
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                SecurityContextId        = Util.GetSecurityContextId(),
            };

            sigExplorer.SetSignatureFile(blob);
            var signature = sigExplorer.Open();

            // 3. Create PDF with verification information from uploaded PDF

            var pdfMarker = new PdfMarker(client);

            pdfMarker.SetFile(blob);

            // Build string with joined names of signers (see method getDisplayName below)
            var signerNames     = Util.JoinStringsPt(signature.Signers.Select(s => getDisplayName(s.Certificate)));
            var allPagesMessage = string.Format("This document was digitally signed by {0}.\nTo verify the signatures go to {1} on {2} and inform the code {3}", signerNames, VerificationSiteNameWithArticle, VerificationSite, formattedVerificationCode);

            // PdfHelper is a class from the Rest PKI Client "fluent API" that helps to create elements and
            // parameters for the PdfMarker.
            var pdf = new PdfHelper();

            // ICP-Brasil logo on bottom-right corner of every page (except on the page which will be created
            // at the end of the document).
            pdfMarker.Marks.Add(
                pdf.Mark()
                .OnAllPages()
                .OnContainer(pdf.Container().Width(1).AnchorRight(1).Height(1).AnchorBottom(1))
                .AddElement(
                    pdf.ImageElement()
                    .WithOpacity(75)
                    .WithImage(StorageMock.GetIcpBrasilLogoContent(), "image/png")
                    )
                );

            // Summary on bottom margin of every page (except on the page which will be created at the end of
            // the document).
            pdfMarker.Marks.Add(
                pdf.Mark()
                .OnAllPages()
                .OnContainer(pdf.Container().Height(2).AnchorBottom().VarWidth().Margins(1.5, 3.5))
                .AddElement(
                    pdf.TextElement()
                    .WithOpacity(75)
                    .AddSection(allPagesMessage)
                    )
                );

            // Summary on right margin of every page (except on the page which will be created at the end of
            // the document), rotated 90 degrees counterclockwise (text goes up).
            pdfMarker.Marks.Add(
                pdf.Mark()
                .OnAllPages()
                .OnContainer(pdf.Container().Width(2).AnchorRight().VarHeight().Margins(1.5, 3.5))
                .AddElement(
                    pdf.TextElement()
                    .Rotate90Counterclockwise()
                    .WithOpacity(75)
                    .AddSection(allPagesMessage)
                    )
                );

            // Create a "manifest" mark on a new page added on the end of the document. We'll add several
            // elements to this mark.
            var manifestMark = pdf.Mark()
                               .OnNewPage()
                               // This mark's container is the whole page with 1-inch margins.
                               .OnContainer(pdf.Container().VarWidthAndHeight().Margins(2.54, 2.54));

            // We'll keep track of our "vertical offset" as we add elements to the mark.
            double verticalOffset = 0;
            double elementHeight;

            elementHeight = 3;
            manifestMark
            // ICP-Brasil logo on the upper-left corner.
            .AddElement(
                pdf.ImageElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).Width(elementHeight /* using elementHeight as width because the image is square */).AnchorLeft())
                .WithImage(StorageMock.GetIcpBrasilLogoContent(), "image/png")
                )
            // QR Code with the verification link on the upper-right corner.
            .AddElement(
                pdf.QRCodeElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).Width(elementHeight /* using elementHeight as width because QR Codes are square */).AnchorRight())
                .WithQRCodeData(verificationLink)
                )
            // Header "VERIFICAÇÃO DAS ASSINATURAS" centered between ICP-Brasil logo and QR Code.
            .AddElement(
                pdf.TextElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset + 0.2).FullWidth())
                .AlignTextCenter()
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize * 1.6).WithText("SIGNATURE\nVERIFICATION"))
                );
            verticalOffset += elementHeight;

            // Vertical padding.
            verticalOffset += 1.7;

            // Header with verification code.
            elementHeight = 2;
            manifestMark.AddElement(
                pdf.TextElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth())
                .AlignTextCenter()
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize * 1.2).WithText(string.Format("Verification Code: {0}", formattedVerificationCode)))
                );
            verticalOffset += elementHeight;

            // Paragraph saying "this document was signed by the following signers etc" and mentioning the
            // time zone of the date/times below.
            elementHeight = 2.5;
            manifestMark.AddElement(
                pdf.TextElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth())
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(string.Format("This document was digitally signed by the following signers on the indicated dates ({0}):", TimeZoneDisplayName)))
                );
            verticalOffset += elementHeight;

            // Iterate signers.
            foreach (var signer in signature.Signers)
            {
                elementHeight = 1.5;

                manifestMark
                // Green "check" or red "X" icon depending on result of validation for this signer.
                .AddElement(
                    pdf.ImageElement()
                    .OnContainer(pdf.Container().Height(0.5).AnchorTop(verticalOffset + 0.2).Width(0.5).AnchorLeft())
                    .WithImage(StorageMock.GetValidationResultIcon(signer.ValidationResults.IsValid), "image/png")
                    )
                // Description of signer (see method getSignerDescription() below).
                .AddElement(
                    pdf.TextElement()
                    .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).VarWidth().Margins(0.8, 0))
                    .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(getSignerDescription(signer)))
                    );

                verticalOffset += elementHeight;
            }

            // Some vertical padding from last signer.
            verticalOffset += 1;

            // Paragraph with link to verification site and citing both the verification code above and the
            // verification link below.
            elementHeight = 2.5;
            manifestMark.AddElement(
                pdf.TextElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth())
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(string.Format("To verify the signatures, go to {0} on ", VerificationSiteNameWithArticle)))
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithColor(Color.Blue).WithText(VerificationSite))
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(" and inform the code above or follow the link below:"))
                );
            verticalOffset += elementHeight;

            // Verification link.
            elementHeight = 1.5;
            manifestMark.AddElement(
                pdf.TextElement()
                .OnContainer(pdf.Container().Height(elementHeight).AnchorTop(verticalOffset).FullWidth())
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithColor(Color.Blue).WithText(verificationLink))
                .AlignTextCenter()
                );

            // Apply marks.
            pdfMarker.Marks.Add(manifestMark);
            var result = pdfMarker.Apply();

            // Return result.
            return(result.GetContent());
        }
Example #11
0
        public ActionResult Index(string userfile)
        {
            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want an audit package to be generated, and that the signed file should be included in the package
                GenerateAuditPackage            = true,
                IncludeSignedFileInAuditPackage = true,
                // In order to generate an audit package, we must also pass Validate = true
                Validate = true,
            };

            // Set the PDF file
            if (string.IsNullOrEmpty(userfile))
            {
                // If no file is passed, we use a previously signed and B-Stamped file
                sigExplorer.SetSignatureFile(Server.MapPath("~/Content/bstamped.pdf"));
            }
            else
            {
                var filename = userfile.Replace("_", ".");                 // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC
                sigExplorer.SetSignatureFile(Server.MapPath("~/App_Data/" + filename));
            }

            // Parameters for the signature validation. We have encapsulated this code in a method to include several
            // possibilities depending on the argument passed. Experiment changing the argument to see different validation
            // configurations. Once you decide which is best for your case, you can place the code directly here.
            setValidationParameters(sigExplorer, 1);
            // try changing this number ---------^ for different validation parameters

            // Call the Open() method, which returns the signature file's information
            var signature = sigExplorer.Open();

            // If the document has been B-Stamped, store the "digest index file" to show a link on the page
            if (signature.BStamp != null)
            {
                var appDataPath = Server.MapPath("~/App_Data");
                if (!Directory.Exists(appDataPath))
                {
                    Directory.CreateDirectory(appDataPath);
                }
                var id       = Guid.NewGuid();
                var filename = id + ".txt";
                signature.BStamp.IndexFile.WriteToFile(Path.Combine(appDataPath, filename));
                ViewBag.BStampIndexFile = filename.Replace(".", "_");
            }

            // Store the generated audit package. Notice that although we asked for its generation,
            // the signature might not have been B-Stamped yet, so an audit package might not be returned.
            if (signature.AuditPackage != null)
            {
                var appDataPath = Server.MapPath("~/App_Data");
                if (!Directory.Exists(appDataPath))
                {
                    Directory.CreateDirectory(appDataPath);
                }
                var id       = Guid.NewGuid();
                var filename = id + ".zip";
                signature.AuditPackage.WriteToFile(Path.Combine(appDataPath, filename));
                ViewBag.AuditPackageFile = filename.Replace(".", "_");
            }

            // Render the information (see file Views/OpenPadesSignatureBStamp/Index.html for more information on the information returned)
            return(View(signature));
        }
        public async Task <ActionResult> Index(string userfile)
        {
            // Get an instance of the PadesSignatureExplorer class, used to open/validate PDF signatures.
            var sigExplorer = new PadesSignatureExplorer(Util.GetRestPkiClient())
            {
                // Specify that we want an audit package to be generated, and that the signed file should be
                // included in the package.
                GenerateAuditPackage            = true,
                IncludeSignedFileInAuditPackage = true,
                // In order to generate an audit package, we must also pass Validate = true.
                Validate = true,
                // Specify the parameters for the signature validation:
                // Accept any PAdES signature as long as the signer has an ICP-Brasil certificate.
                DefaultSignaturePolicyId = StandardPadesSignaturePolicies.Basic,
                // Specify the security context to be used to determine trust in the certificate chain. We
                // have encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId()
            };

            // Set the PDF file.
            if (!string.IsNullOrEmpty(userfile))
            {
                // Verify if the provided userfile exits and get its absolute path.
                string userfilePath;
                if (!StorageMock.TryGetFile(userfile, out userfilePath))
                {
                    return(HttpNotFound());
                }

                // Set the userfile's absolute path to the PadesSignatureExplorer instance.
                sigExplorer.SetSignatureFile(userfilePath);
            }
            else
            {
                // If no userfile is passed, we use a previously signed and B-Stamped file.
                sigExplorer.SetSignatureFile(StorageMock.GetSampleBStampedPath());
            }

            // Call the Open() method, which returns the signature file's information.
            var signature = await sigExplorer.OpenAsync();

            // If the document has been B-Stamped, store the "digest index file" to show a link on the page.
            string indexFileId = null;

            if (signature.BStamp != null)
            {
                using (var indexFileStream = signature.BStamp.IndexFile.OpenRead()) {
                    indexFileId = StorageMock.Store(indexFileStream, ".txt");
                }
            }

            // Store the generated audit package. Notice that although we asked for its generation, the
            // signature might not have been B-Stamped yet, so an audit package might not be returned.
            string auditPkgId = null;

            if (signature.AuditPackage != null)
            {
                using (var auditPkgStream = signature.AuditPackage.OpenRead()) {
                    auditPkgId = StorageMock.Store(auditPkgStream, ".zip");
                }
            }

            // Render the information (see file OpenPadesSignatureBStamp/Index.html for more
            // information on the information returned).
            return(View(new OpenPadesSignatureBStampModel()
            {
                Signature = signature,
                BStampIndexFile = indexFileId,
                AuditPackageFile = auditPkgId
            }));
        }