Example #1
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Get an instance of the XmlElementSignatureStarter class, responsible for receiving the signature elements and start the
                // signature process
                var signatureStarter = new XmlElementSignatureStarter(Util.GetRestPkiClient());

                // Set the XML to be signed, a sample Brazilian fiscal invoice pre-generated
                signatureStarter.SetXml(Util.GetSampleNFeContent());

                // Set the ID of the element to be signed (this ID is present in the invoice above)
                signatureStarter.SetToSignElementId("NFe35141214314050000662550010001084271182362300");

                // Set the signature policy
                signatureStarter.SetSignaturePolicy(StandardXmlSignaturePolicies.PkiBrazil.NFePadraoNacional);

                // Set the security context to be used to determine trust in the certificate chain
                signatureStarter.SetSecurityContext(Util.GetSecurityContextId());

                // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character
                // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the
                // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature
                // on the POST action below (this should not be mistaken with the API access token).
                var token = signatureStarter.StartWithWebPki();

                ViewState["Token"] = token;
            }
        }
Example #2
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the
                // signature process
                var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient())
                {
                    // Set the unit of measurement used to edit the pdf marks and visual representations
                    MeasurementUnits = PadesMeasurementUnits.Centimeters,

                    // Set the signature policy
                    SignaturePolicyId = StandardPadesSignaturePolicies.Basic,

                    // Set the security context to be used to determine trust in the certificate chain
                    SecurityContextId = Util.GetSecurityContextId(),

                    // Set a visual representation for the signature (see function below)
                    VisualRepresentation = getVisualRepresentation(),
                };

                /*
                 * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that
                 * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number
                 * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature.
                 * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous
                 * signatures, otherwise such signatures would be made invalid by the changes to the document (see property
                 * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occur with signature visual representations.
                 *
                 * We have encapsulated this code in a method to include several possibilities depending on the argument passed.
                 * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case,
                 * you can place the code directly here.
                 */
                //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1));

                // If the user was redirected here by Upload (signature with file uploaded by user), the "userfile" URL argument
                // will contain the filename under the "App_Data" folder. Otherwise (signature with server file), we'll sign a sample
                // document.
                UserFile = Request.QueryString["userfile"];
                if (string.IsNullOrEmpty(UserFile))
                {
                    // Set the PDF to be signed as a byte array
                    signatureStarter.SetPdfToSign(Util.GetSampleDocContent());
                }
                else
                {
                    // Set the path of the file to be signed
                    signatureStarter.SetPdfToSign(Server.MapPath("~/App_Data/" + UserFile));
                }

                // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character
                // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the
                // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature
                // on the POST action below (this should not be mistaken with the API access token).
                var token = signatureStarter.StartWithWebPki();

                ViewState["Token"] = token;
            }
        }
Example #3
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Get an instance of the CadesSignatureStarter class, responsible for receiving the signature elements and start the
                // signature process
                var signatureStarter = Util.GetRestPkiClient().GetCadesSignatureStarter();

                // Set the signature policy
                signatureStarter.SetSignaturePolicy(StandardCadesSignaturePolicies.PkiBrazil.AdrBasica);

                // Set the security context to be used to determine trust in the certificate chain
                signatureStarter.SetSecurityContext(Util.GetSecurityContextId());

                // Optionally, set whether the content should be encapsulated in the resulting CMS. If this parameter is ommitted,
                // the following rules apply:
                // - If no CmsToCoSign is given, the resulting CMS will include the content
                // - If a CmsToCoSign is given, the resulting CMS will include the content if and only if the CmsToCoSign also includes the content
                signatureStarter.SetEncapsulateContent(true);

                UserFile = Request.QueryString["userfile"];
                CmsFile  = Request.QueryString["cmsfile"];
                if (!String.IsNullOrEmpty(UserFile))
                {
                    // If the user was redirected here by Upload (signature with file uploaded by user), the "userfile" URL argument
                    // will contain the filename under the "App_Data" folder.
                    signatureStarter.SetFileToSign(Server.MapPath("~/App_Data/" + UserFile));
                }
                else if (!String.IsNullOrEmpty(CmsFile))
                {
                    /*
                     * If the URL argument "cmsfile" is filled, the user has asked to co-sign a previously signed CMS. We'll set the path to the CMS
                     * to be co-signed, which was perviously saved in the App_Data folder by the POST action on this controller. Note two important things:
                     *
                     * 1. The CMS to be co-signed must be set using the method "SetCmsToCoSign", not the method "SetContentToSign" nor "SetFileToSign"
                     *
                     * 2. Since we're creating CMSs with encapsulated content (see call to SetEncapsulateContent above), we don't need to set the content
                     *    to be signed, REST PKI will get the content from the CMS being co-signed.
                     */
                    signatureStarter.SetCmsToCoSign(Server.MapPath("~/App_Data/" + CmsFile));
                }
                else
                {
                    // If both userfile and cmsfile are null, this is the "signature with server file" case. We'll set the path of the file to be signed
                    signatureStarter.SetFileToSign(Util.GetSampleDocPath());
                }

                // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character
                // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the
                // signWithRestPki() method on the Web PKI component (see javascript on the view) and also to complete the signature
                // on the Click-event handler below (this should not be mistaken with the API access token).
                var token = signatureStarter.StartWithWebPki();

                ViewState["Token"] = token;
            }
        }
Example #4
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Get an instance of the Authentication class
                var auth = Util.GetRestPkiClient().GetAuthentication();

                // Call the StartWithWebPki() method, which initiates the authentication. This yields the "token", a 22-character
                // case-sensitive URL-safe string, which represents this authentication process. We'll use this value to call the
                // signWithRestPki() method on the Web PKI component (see signature-form.js) and also to call the
                // CompleteWithWebPki() method on the Click-event handler below (this should not be mistaken with the API access token).
                var token = auth.StartWithWebPki(Util.GetSecurityContextId());

                // We'll need the token later, so we'll put it on ViewState and we'll render a hidden field on the page with it
                ViewState["Token"] = token;
            }
        }
Example #5
0
        public static string Start(int id)
        {
            // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the
            // signature process
            var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient())
            {
                // Set the unit of measurement used to edit the pdf marks and visual representations
                MeasurementUnits = PadesMeasurementUnits.Centimeters,

                // Set the signature policy
                SignaturePolicyId = StandardPadesSignaturePolicies.Basic,

                // Set the security context to be used to determine trust in the certificate chain
                SecurityContextId = Util.GetSecurityContextId(),

                // Set a visual representation for the signature (see function below)
                VisualRepresentation = getVisualRepresentation(),
            };

            /*
             * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that
             * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number
             * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature.
             * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous
             * signatures, otherwise such signatures would be made invalid by the changes to the document (see property
             * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occurr with signature visual representations.
             *
             * We have encapsulated this code in a method to include several possibilities depending on the argument passed.
             * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case,
             * you can place the code directly here.
             */
            //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1));

            // Set the PDF to be signed
            signatureStarter.SetPdfToSign(Util.GetBatchDocContent(id));

            // Call the StartWithWebPki() method, which initiates the signature. This yields the token, a 43-character
            // case-sensitive URL-safe string, which identifies this signature process. We'll use this value to call the
            // signWithRestPki() method on the Web PKI component (see batch-signature-optimized-form.js) and also to complete
            // the signature on the POST action below (this should not be mistaken with the API access token).
            var token = signatureStarter.StartWithWebPki();

            // Send to the javascript the token of the signature process to be used to call Web PKI to perform the signature
            return(token);
        }
Example #6
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;
        }
Example #7
0
        private void startNextSignature()
        {
            // Increment the index of the document currently being signed
            DocumentIndex += 1;

            // Check if we have reached the end of the batch, in which case we fill the hidden field "TokenField" with value "(end)",
            // which signals to the javascript on batch-signature-form.js that the process is completed and the page can be unblocked.
            if (DocumentIndex == DocumentIds.Count)
            {
                TokenField.Value = "(end)";
                return;
            }

            // Get the ID of the document currently being signed
            var docId = DocumentIds[DocumentIndex];

            string token;

            try {
                // Get an instance of the PadesSignatureStarter class, responsible for receiving the signature elements and start the
                // signature process
                var signatureStarter = new PadesSignatureStarter(Util.GetRestPkiClient())
                {
                    // Set the unit of measurement used to edit the pdf marks and visual representations
                    MeasurementUnits = PadesMeasurementUnits.Centimeters,

                    // Set the signature policy
                    SignaturePolicyId = StandardPadesSignaturePolicies.Basic,

                    // Set the security context to be used to determine trust in the certificate chain
                    SecurityContextId = Util.GetSecurityContextId(),

                    // Set a visual representation for the signature (see function below)
                    VisualRepresentation = getVisualRepresentation(),
                };

                /*
                 * Optionally, add marks to the PDF before signing. These differ from the signature visual representation in that
                 * they are actually changes done to the document prior to signing, not binded to any signature. Therefore, any number
                 * of marks can be added, for instance one per page, whereas there can only be one visual representation per signature.
                 * However, since the marks are in reality changes to the PDF, they can only be added to documents which have no previous
                 * signatures, otherwise such signatures would be made invalid by the changes to the document (see property
                 * PadesSignatureStarter.BypassMarksIfSigned). This problem does not occurr with signature visual representations.
                 *
                 * We have encapsulated this code in a method to include several possibilities depending on the argument passed.
                 * Experiment changing the argument to see different examples of PDF marks. Once you decide which is best for your case,
                 * you can place the code directly here.
                 */
                //signatureStarter.PdfMarks.Add(PadesVisualElements.GetPdfMark(1));

                // Set the PDF to be signed
                signatureStarter.SetPdfToSign(Util.GetBatchDocContent(docId));

                // Call the StartWithWebPki() method, which initiates the signature.
                token = signatureStarter.StartWithWebPki();
            } catch (ValidationException ex) {
                // One or more validations failed. We log the error, update the page with a summary of what happened to this document and start the next signature
                setValidationError(ex.ValidationResults);
                startNextSignature();
                return;
            } catch (Exception ex) {
                // An error has occurred. We log the error, update the page with a summary of what happened to this document and start the next signature
                setError(ex.Message);
                startNextSignature();
                return;
            }

            // Send to the javascript the token of the signature process to be used to call Web PKI to perform the signature
            TokenField.Value = token;
        }
        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("Este documento foi assinado digitalmente por {0}.\nPara verificar a validade das assinaturas acesse {1} em {2} e informe o código {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(Util.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(Util.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("VERIFICAÇÃO DAS\nASSINATURAS"))
                );
            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("Código para verificação: {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("Este documento foi assinado digitalmente pelos seguintes signatários nas datas indicadas ({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(Util.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("Para verificar a validade das assinaturas, acesse {0} em ", VerificationSiteNameWithArticle)))
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithColor(Color.Blue).WithText(VerificationSite))
                .AddSection(pdf.TextSection().WithFontSize(NormalFontSize).WithText(" e informe o código acima ou acesse o link abaixo:"))
                );
            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());
        }