public ActionResult Index(SignatureStartModel model)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

            try {
                // Verify if the userfile exists and get its absolute path.
                string userfilePath;
                if (!StorageMock.TryGetFile(model.UserFile, out userfilePath))
                {
                    return(HttpNotFound());
                }

                // Decode the user's certificate.
                var cert = PKCertificate.Decode(model.CertContent);

                // Get an instance of the PadesSigner class.
                var padesSigner = new PadesSigner();

                // Set the file to be signed.
                padesSigner.SetPdfToSign(userfilePath);

                // Set the signer certificate.
                padesSigner.SetSigningCertificate(cert);

                // Set the signature policy.
                padesSigner.SetPolicy(GetSignaturePolicy());

                // Set a visual representation for the signature.
                padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert));

                // Generate the "to-sign-bytes". This method also yields the signature algorithm that must
                // be used on the client-side, based on the signature policy, as well as the "transfer data",
                // a byte-array that will be needed on the next step.
                toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData);
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // encoding cannot be read or if the certificate is expired.
                ModelState.AddModelError("", ex.ValidationResults.ToString());
                return(View());
            }

            // On the next step (Complete action), we'll need once again some information:
            // - The thumbprint of the selected certificate.
            // - The "transfer data" used to validate the signature in complete action. Its content is stored in
            //   a temporary file (with extension .bin) to be shared with the Complete action.
            // - The "to-sign-hash" (digest of the "to-sign-bytes") to be signed. (see signature-complete-form.js)
            // - The OID of the digest algorithm to be used during the signature operation.
            // We'll store these values on TempData, which is a dictionary shared between actions.
            TempData["SignatureCompleteModel"] = new SignatureCompleteModel()
            {
                CertThumb          = model.CertThumb,
                TransferDataFileId = StorageMock.Store(transferData, ".bin"),
                ToSignHash         = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes),
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            };

            return(RedirectToAction("Complete", new { userfile = model.UserFile }));
        }
        public async Task <ActionResult> 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. We have
                // encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId(),

                // Set a visual representation for the signature.
                VisualRepresentation = PadesVisualElements.GetVisualRepresentationForRestPki()
            };

            // Set the document to be signed based on its ID (passed to us from the page).
            signatureStarter.SetPdfToSign(StorageMock.GetBatchDocPath(id));

            /*
             *      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));

            // 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-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 = await signatureStarter.StartWithWebPkiAsync();

            // Return a JSON with the token obtained from REST PKI. (the page will use jQuery to decode this
            // value)
            return(Json(token));
        }
        public ActionResult Start(BatchSignatureStartRequest request)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

            try {
                // Decode the user's certificate
                var cert = PKCertificate.Decode(request.CertContent);

                // Instantiate a PadesSigner class
                var padesSigner = new PadesSigner();

                // Set the PDF to sign, which in the case of this example is one of the batch documents
                padesSigner.SetPdfToSign(StorageMock.GetBatchDocPath(request.Id));

                // Set the signer certificate
                padesSigner.SetSigningCertificate(cert);

                // Set the signature policy.
                padesSigner.SetPolicy(GetSignaturePolicy());

                // Set a visual representation for the signature.
                padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert));

                // Generate the "to-sign-bytes". This method also yields the signature algorithm that must
                // be used on the client-side, based on the signature policy, as well as the "transfer data",
                // a byte-array that will be needed on the next step.
                toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData);
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // encoding cannot be read or if the certificate is expired.
                return(new HttpStatusCodeResult(500, ex.ValidationResults.ToString()));
            }

            // For the next steps, we'll need once again some information:
            // - The "transfer data" filename. Its content is stored in a temporary file (with extension .bin) to
            // be shared with the Complete action.
            // - The "to-sign-hash" (digest of the "to-sign-bytes"). And the OID of the digest algorithm to be
            // used during the signature operation. this information is need in the signature computation with
            // Web PKI component. (see batch-signature-form.js)
            return(Json(new BatchSignatureStartResponse()
            {
                TransferDataFileId = StorageMock.Store(transferData, ".bin"),
                ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes),
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            }));
        }
Beispiel #4
0
        public async Task <string> Start(string userfile)
        {
            var storage = new Storage(hostingEnvironment);
            var client  = Util.GetRestPkiClient(restPkiConfig);

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

                // Set the signature policy
                SignaturePolicyId = StandardPadesSignaturePolicies.PkiBrazil.BasicWithPkiBrazilCerts,
                // Note: Depending on the signature policy chosen above, setting the security context below may be mandatory (this is not
                // the case for ICP-Brasil policies, which will automatically use the PkiBrazil security context if none is passed)

                // Optionally, set a SecurityContext to be used to determine trust in the certificate chain
                //SecurityContextId = new Guid("ID OF YOUR CUSTOM SECURITY CONTEXT"),
                // For instance, to use the test certificates on Lacuna Test PKI (for development purposes only!):
                //SecurityContextId = new Guid("803517ad-3bbc-4169-b085-60053a8f6dbf"),

                // Set a visual representation for the signature
                VisualRepresentation = new PadesVisualRepresentation()
                {
                    // The tags {{name}} and {{br_cpf_formatted}} will be substituted according to the user's certificate
                    //
                    //		name             : full name of the signer
                    //		br_cpf_formatted : if the certificate is ICP-Brasil, contains the signer's CPF
                    //
                    // For a full list of the supported tags, see: https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md
                    Text = new PadesVisualText("Signed by {{name}} ({{br_cpf_formatted}})")
                    {
                        // Specify that the signing time should also be rendered
                        IncludeSigningTime = true,

                        // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if not set the default is Left
                        HorizontalAlign = PadesTextHorizontalAlign.Left
                    },

                    // We'll use as background the image in Content/PdfStamp.png
                    Image = new PadesVisualImage(storage.GetPdfStampContent(), "image/png")
                    {
                        // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque).
                        Opacity = 50,

                        // Align the image to the right
                        HorizontalAlign = PadesHorizontalAlign.Right
                    },

                    // Position of the visual representation. 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 signature positioning. Once you decide which is best for your case, you can place the code directly here.
                    Position = PadesVisualElements.GetVisualPositioning(client, 1)
                }
            };

            // Below we'll either set the PDF file to be signed. Prefer passing a path or a stream instead of the file's contents
            // as a byte array to prevent memory allocation issues with large files.

            // If the "userfile" URL argument is set, it will contain the filename under the "App_Data" folder. Otherwise
            // (signature with server file), we'll sign a sample document.
            if (string.IsNullOrEmpty(userfile))
            {
                signatureStarter.SetPdfToSign(storage.GetSampleDocPath());
            }
            else
            {
                Stream userFileStream;
                if (!storage.TryOpenRead(userfile, out userFileStream))
                {
                    throw new Exception("File not found");
                }
                signatureStarter.SetPdfToSign(userFileStream);
            }

            /*
             *      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(storage, 1));

            // Call the StartWithWebPkiAsync() 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 angular controller) and also to complete
            // the signature on the POST action below (this should not be mistaken with the API access token).
            var token = await signatureStarter.StartWithWebPkiAsync();

            return(token);
        }
        public ActionResult Index(string userfile)
        {
            // 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 a SecurityContext to be used to determine trust in the certificate chain
                SecurityContextId = StandardSecurityContexts.PkiBrazil,
                // Note: By changing the SecurityContext above you can accept certificates from a custom security context created on the Rest PKI website.

                // Set a visual representation for the signature
                VisualRepresentation = new PadesVisualRepresentation()
                {
                    // The tags {{signerName}} and {{signerNationalId}} will be substituted according to the user's certificate
                    // signerName -> full name of the signer
                    // signerNationalId -> if the certificate is ICP-Brasil, contains the signer's CPF
                    Text = new PadesVisualText("Signed by {{signerName}} ({{signerNationalId}})")
                    {
                        // Specify that the signing time should also be rendered
                        IncludeSigningTime = true,

                        // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if not set the default is Left
                        HorizontalAlign = PadesTextHorizontalAlign.Left
                    },

                    // We'll use as background the image in Content/PdfStamp.png
                    Image = new PadesVisualImage(Util.GetPdfStampContent(), "image/png")
                    {
                        // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque).
                        Opacity = 50,

                        // Align the image to the right
                        HorizontalAlign = PadesHorizontalAlign.Right
                    },

                    // Position of the visual representation. 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 signature positioning. Once you decide which is best for your case, you can place the code directly here.
                    Position = PadesVisualElements.GetVisualPositioning(1)
                },
            };

            // If the user was redirected here by UploadController (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.
            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.Replace("_", ".")));                 // Note: we're passing the filename argument with "." as "_" because of limitations of ASP.NET MVC
            }

            /*
             *      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));

            // 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();

            // The token acquired above can only be used for a single signature attempt. In order to retry the signature it is
            // necessary to get a new token. This can be a problem if the user uses the back button of the browser, since the
            // browser might show a cached page that we rendered previously, with a now stale token. To prevent this from happening,
            // we call the method SetNoCacheHeaders() (in BaseController) which sets HTTP headers to prevent caching of the page.
            base.SetNoCacheHeaders();

            // Render the signature page with the token obtained from REST PKI
            return(View(new Models.PadesSignatureModel()
            {
                Token = token,
                UserFile = userfile
            }));
        }
        public async Task <ActionResult> Index(string userfile)
        {
            // Verify if the userfile exists and get its absolute path.
            string userfilePath;

            if (!StorageMock.TryGetFile(userfile, out userfilePath))
            {
                return(HttpNotFound());
            }

            // 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. We have
                // encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId(),

                // Set a visual representation for the signature.
                VisualRepresentation = PadesVisualElements.GetVisualRepresentationForRestPki()
            };

            // Set the file to be signed.
            signatureStarter.SetPdfToSign(userfilePath);

            /*
             *      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));

            // 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
            // signature-forms.js) and also to complete the signature on the POST action below (this should
            // not be mistaken with the API access token).
            var token = await signatureStarter.StartWithWebPkiAsync();

            // The token acquired above can only be used for a single signature attempt. In order to retry
            // the signature it is necessary to get a new token. This can be a problem if the user uses the
            // back button of the browser, since the browser might show a cached page that we rendered
            // previously, with a now stale token. To prevent this from happening, we call the method
            // SetNoCacheHeaders() (in BaseController) which sets HTTP headers to prevent caching of the
            // page.
            base.SetNoCacheHeaders();

            // Render the signature page with the token obtained from REST PKI.
            return(View(new SignatureModel()
            {
                Token = token,
                UserFile = userfile
            }));
        }
        public ActionResult Start(SignatureStartModel model)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

            try {
                // Verify if the userfile exists and get its absolute path.
                string userfilePath;
                if (!StorageMock.TryGetFile(model.UserFile, out userfilePath))
                {
                    return(HttpNotFound());
                }

                // Decode the user's certificate.
                var cert = PKCertificate.Decode(model.CertContent);

                // Get an instance of the PadesSigner class.
                var padesSigner = new PadesSigner();

                // Set the file to be signed.
                padesSigner.SetPdfToSign(userfilePath);

                // REQUIRED!
                // Provide the signer's certificate. You must sign with a valid digital
                // certificate of a doctor, who was registered on CRM. In this sample,
                // we used a sample certificate stored on server to do the execute this
                // sample.
                padesSigner.SetSigningCertificate(cert);

                // REQUIRED!
                // Define the trust arbitrator, which will configure the signer to
                // some kind of certificate. In the case of this sample, only
                // ICP-Brasil certificates will be accepted in the defined standard.
                var trustArbitrator = new LinkedTrustArbitrator(TrustArbitrators.PkiBrazil);
#if DEBUG
                // For development purposes, we also trust in Lacuna Software's test certificates.
                var lacunaRoot = Lacuna.Pki.PKCertificate.Decode(Convert.FromBase64String("MIIGGTCCBAGgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBfMQswCQYDVQQGEwJCUjETMBEGA1UECgwKSUNQLUJyYXNpbDEdMBsGA1UECwwUTGFjdW5hIFNvZnR3YXJlIC0gTFMxHDAaBgNVBAMME0xhY3VuYSBSb290IFRlc3QgdjEwHhcNMTUwMTE2MTk1MjQ1WhcNMjUwMTE2MTk1MTU1WjBfMQswCQYDVQQGEwJCUjETMBEGA1UECgwKSUNQLUJyYXNpbDEdMBsGA1UECwwUTGFjdW5hIFNvZnR3YXJlIC0gTFMxHDAaBgNVBAMME0xhY3VuYSBSb290IFRlc3QgdjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCDm5ey0c4ij8xnDnV2EBATjJbZjteEh8BBiGtVx4dWpXbWQ6hEw8E28UyLsF6lCM2YjQge329g7hMANnrnrNCvH1ny4VbhHMe4eStiik/GMTzC79PYS6BNfsMsS6+W18a45eyi/2qTIHhJYN8xS4/7pAjrVpjL9dubALdiwr26I3a4S/h9vD2iKJ1giWnHU74ckVp6BiRXrz2ox5Ps7p420VbVU6dTy7QR2mrhAus5va9VeY1LjvCH9S9uSf6kt+HP1Kj7hlOOlcnluXmuD/IN68/CQeC+dLOr0xKmDvYv7GWluXhxpUZmh6NaLzSGzGNACobOezKmby06s4CvsmMKQuZrTx113+vJkYSgI2mBN5v8LH60DzuvIhMvDLWPZCwfnyGCNHBwBbdgzBWjsfuSFJyaKdJLmpu5OdWNOLjvexqEC9VG83biYr+8XMiWl8gUW8SFqEpNoLJ59nwsRf/R5R96XTnG3mdVugcyjR9xe/og1IgJFf9Op/cBgCjNR/UAr+nizHO3Q9LECnu1pbTtGZguGDMABc+/CwKyxirwlRpiu9DkdBlNRgdd5IgDkcgFkTjmA41ytU0LOIbxpKHn9/gZCevq/8CyMa61kgjzg1067BTslex2xUZm44oVGrEdx5kg/Hz1Xydg4DHa4qlG61XsTDJhM84EvnJr3ZTYOwIDAQABo4HfMIHcMDwGA1UdIAQ1MDMwMQYFYEwBAQAwKDAmBggrBgEFBQcCARYaaHR0cDovL2xhY3VuYXNvZnR3YXJlLmNvbS8wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NhdGVzdC5sYWN1bmFzb2Z0d2FyZS5jb20vY3Jscy9yb290MB8GA1UdIwQYMBaAFPtdXjCI7ZOfGUg8mrCoEw9z9zywMB0GA1UdDgQWBBT7XV4wiO2TnxlIPJqwqBMPc/c8sDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQ0FAAOCAgEAN/b8hNGhBrWiuE67A8kmom1iRUl4b8FAA8PUmEocbFv/BjLpp2EPoZ0C+I1xWT5ijr4qcujIMsjOCosmv0M6bzYvn+3TnbzoZ3tb0aYUiX4ZtjoaTYR1fXFhC7LJTkCN2phYdh4rvMlLXGcBI7zA5+Ispm5CwohcGT3QVWun2zbrXFCIigRrd3qxRbKLxIZYS0KW4X2tetRMpX6DPr3MiuT3VSO3WIRG+o5Rg09L9QNXYQ74l2+1augJJpjGYEWPKzHVKVJtf1fj87HN/3pZ5Hr2oqDvVUIUGFRj7BSel9BgcgVaWqmgTMSEvQWmjq0KJpeqWbYcXXw8lunuJoENEItv+Iykv3NsDfNXgS+8dXSzTiV1ZfCdfAjbalzcxGn522pcCceTyc/iiUT72I3+3BfRKaMGMURu8lbUMxd/38Xfut3Kv5sLFG0JclqD1rhI15W4hmvb5bvol+a/WAYT277jwdBO8BVSnJ2vvBUzH9KAw6pAJJBCGw/1dZkegLMFibXdEzjAW4z7wyx2c5+cmXzE/2SFV2cO3mJAtpaO99uwLvj3Y3quMBuIhDGD0ReDXNAniXXXVPfE96NUcDF2Dq2g8kj+EmxPy6PGZ15p1XZO1yiqsGEVreIXqgcU1tPUv8peNYb6jHTHuUyXGTzbsamGZFEDsLG7NRxg0eZWP1w="));
                trustArbitrator.Add(new TrustedRoots(lacunaRoot));
#endif
                // REQUIRED!
                // Use a policy accepted by ICP-Brasil. We use the trust arbitrator
                // defined above to configure the policy.
                padesSigner.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(trustArbitrator));

                // REQUIRED!
                // Use a custom signature field name. This field MUST have the
                // "Emitente" keyword as the last keyword.
                padesSigner.SetCustomSignatureFieldName("Signature1 Emitente");

                // REQUIRED!
                // Set Certification Level to not allow changes after signed.
                padesSigner.SetCertificationLevel(PadesCertificationLevel.CertifiedNoChangesAllowed);

                // Set a visual representation for the signature.
                padesSigner.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(cert));

                // Generate the "to-sign-bytes". This method also yields the signature algorithm that must
                // be used on the client-side, based on the signature policy, as well as the "transfer data",
                // a byte-array that will be needed on the next step.
                toSignBytes = padesSigner.GetToSignBytes(out signatureAlg, out transferData);
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // encoding cannot be read or if the certificate is expired.
                ModelState.AddModelError("", ex.ValidationResults.ToString());
                return(View());
            }

            // On the next step (Complete action), we'll need once again some information:
            // - The thumbprint of the selected certificate.
            // - The "transfer data" used to validate the signature in complete action. Its content is stored in
            //   a temporary file (with extension .bin) to be shared with the Complete action.
            // - The "to-sign-hash" (digest of the "to-sign-bytes") to be signed. (see signature-complete-form.js)
            // - The OID of the digest algorithm to be used during the signature operation.
            // We'll store these values on TempData, which is a dictionary shared between actions.
            TempData["SignatureCompleteModel"] = new SignatureCompleteModel()
            {
                CertThumb          = model.CertThumb,
                TransferDataFileId = StorageMock.Store(transferData, ".bin"),
                ToSignHash         = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes),
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            };

            return(RedirectToAction("Complete", new { userfile = model.UserFile }));
        }
Beispiel #8
0
        public async Task <ActionResult> Index(SignatureStartModel model)
        {
            ClientSideSignatureInstructions signatureParams;

            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 a SecurityContext to be used to determine trust in the certificate chain.
                    SecurityContextId = Util.GetSecurityContextId(),

                    // Set a visual representation for the signature.
                    VisualRepresentation = new PadesVisualRepresentation()
                    {
                        // The tags {{name}} and {{national_id}} will be substituted according to the user's
                        // certificate:
                        //
                        //		name        : Full name of the signer;
                        //		national_id : If the certificate is ICP-Brasil, contains the signer's CPF.
                        //
                        // For a full list of the supported tags, see:
                        // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md
                        Text = new PadesVisualText("Signed by {{name}} ({{national_id}})")
                        {
                            // Specify that the signing time should also be rendered.
                            IncludeSigningTime = true,

                            // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if
                            // not set the default is Left.
                            HorizontalAlign = PadesTextHorizontalAlign.Left
                        },

                        // We'll use as background the image in Content/PdfStamp.png.
                        Image = new PadesVisualImage(Util.GetPdfStampContent(), "image/png")
                        {
                            // Opacity is an integer from 0 to 100. (0 is completely transparent, 100 is
                            // completely opaque)
                            Opacity = 50,

                            // Align the image to the right.
                            HorizontalAlign = PadesHorizontalAlign.Right
                        },

                        // Position of the visual representation. 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 signature positioning. Once you
                        // decide which is best for your case, you can place the code directly here.
                        Position = PadesVisualElements.GetVisualPositioning(1)
                    }
                };

                // Set certificate's content. (received from a hidden field on the form submission, its value
                // is filled on javascript, see signature-start-form.js)
                signatureStarter.SetSignerCertificate(model.CertContent);

                // Set PDF to be signed.
                signatureStarter.SetPdfToSign(Util.GetSampleDocPath());

                /*
                 *                  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));

                // Call the StartAsync() method, which initiates the signature. This yields the parameters
                // for the signature using the certificates.
                signatureParams = await signatureStarter.StartAsync();
            } catch (ValidationException ex) {
                // Return to Index view rendering the error message.
                ModelState.AddModelError("", ex.Message);
                return(View());
            }

            // On the next step (Complete action), we'll need once again some information:
            // - The token that identifies the signature process on REST PKI service.
            // - The thumbprint of the selected certificate.
            // - The "to-sign-hash" to be signed. (see signature-complete-form.js)
            // - The OID of the digest algorithm to be used during the signature operation.
            // We'll store these values on TempData, which is a dictionary shared between actions.
            TempData["SignatureCompleteModel"] = new SignatureCompleteModel()
            {
                Token              = signatureParams.Token,
                CertThumb          = model.CertThumb,
                ToSignHash         = signatureParams.ToSignHash,
                DigestAlgorithmOid = signatureParams.DigestAlgorithmOid
            };

            return(RedirectToAction("Complete"));
        }
Beispiel #9
0
        /**
         * GET /PadesCloudOauthSdk/Complete
         *
         * This action will complete the authentication process and create a signature using a session
         * token returned by user. Also, we recover the parameter "customState" containing the id of the
         * file that will be signed.
         */
        public async Task <ActionResult> Complete(string code, string state)
        {
            byte[] signatureContent;
            PKCertificateWithKey signingCertificate;

            try {
                // Get an instance of the TrustServiceManager class, responsible for communicating with PSCs
                // and handling the OAuth flow.
                var manager = Util.GetTrustServicesManager();

                // Complete the authentication process, recovering the session info to be used on the
                // signature and the custom state (fileId).
                var completeAuthResult = await manager.CompleteAuthAsync(code, state);

                // Recover file to be sigend on custom state parameter.
                var userfile = completeAuthResult.CustomState;

                // Verify if the userfile exists and get its absolute path.
                string userfilePath;
                if (!StorageMock.TryGetFile(userfile, out userfilePath))
                {
                    return(HttpNotFound());
                }

                // Get an instance of the PadesSigner class, responsible for receiving the signature elements
                // and performing the local signature.
                var signer = new PadesSigner();

                // Set signature policy.
                signer.SetPolicy(GetSignaturePolicy());

                // Set file to be signed.
                signer.SetPdfToSign(userfilePath);

                // Recover the interface for the cloud certificate to be passed to PadesSigner class.
                var certificatesWithKey = await completeAuthResult.GetCertificatesWithKeyAsync();

                signingCertificate = certificatesWithKey.First();
                signer.SetSigningCertificate(signingCertificate);

                // Set a visual representation for the signature.
                signer.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(signingCertificate.Certificate));

                // Call ComputeSignature(), which does all the work, including validation of the signer's certificate and of the resulting signature
                signer.ComputeSignature();

                // Get the signed PDF as an array of bytes
                signatureContent = signer.GetPadesSignature();
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // encoding cannot be read or if the certificate is expired.
                ModelState.AddModelError("", ex.ValidationResults.ToString());
                return(View());
            }

            return(View("SignatureInfo", new SignatureInfoModel()
            {
                // Store the signature file on the folder "App_Data/".
                // With this filename, it can show a link to download the signature file.
                File = StorageMock.Store(signatureContent, ".pdf"),
                SignerCertificate = signingCertificate.Certificate
            }));
        }
Beispiel #10
0
        public async Task <ActionResult> Start(BatchSignatureStartRequest request)
        {
            // Recover the batch information based on its ID, which contains the user's certificate.
            var batchInfo = batches[request.BatchId];

            // 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 user's certificate. Notice that this step is not necessary on the regular batch
                // signature example. This enhances the performance of the batch processing.
                SignerCertificate = Convert.FromBase64String(batchInfo.Certificate),

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

                // Set a SecurityContext to be used to determine trust in the certificate chain. We have
                // encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId(),

                // Set a visual representation for the signature.
                VisualRepresentation = new PadesVisualRepresentation()
                {
                    // The tags {{name}} and {{national_id}} will be substituted according to the user's
                    // certificate:
                    //
                    //      name        : Full name of the signer;
                    //      national_id : If the certificate is ICP-Brasil, contains the signer's CPF.
                    //
                    // For a full list of the supported tags, see:
                    // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md
                    Text = new PadesVisualText("Signed by {{name}} ({{national_id}})")
                    {
                        // Specify that the signing time should also be rendered.
                        IncludeSigningTime = true,

                        // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if not
                        // set the default is Left.
                        HorizontalAlign = PadesTextHorizontalAlign.Left
                    },

                    // We'll use as background the image in Content/PdfStamp.png.
                    Image = new PadesVisualImage(Util.GetPdfStampContent(), "image/png")
                    {
                        // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is
                        // completely opaque).
                        Opacity = 50,

                        // Align the image to the right.
                        HorizontalAlign = PadesHorizontalAlign.Right
                    },

                    // Position of the visual representation. 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 signature positioning. Once you decide which
                    // is best for your case, you can place the code directly here.
                    Position = PadesVisualElements.GetVisualPositioning(1)
                }
            };

            // Set the document to be signed based on its ID. (passed to us from the page)
            signatureStarter.SetPdfToSign(Util.GetBatchDocPath(request.DocumentId));

            // Call the Start() method, which initiates the signature. Notice that, on the regular signature
            // example, we call the StartWithRestPki() method, which is simpler but with worse performance.
            // The Start() method will yield not only the token, a 43-character case-sensitive URL-safe
            // string which identifies this signature process, but also the data that should be used to call
            // the signHash() function on the Web PKI component (instead of the signWithRestPki() function,
            // which is also simpler but far slower).
            var signatureParams = await signatureStarter.StartAsync();

            // Notice: it is not necessary to call SetNoCacheHeaders() because this action is a POST action,
            // therefore no caching of the response will be made by browsers.

            // Return a JSON with the token obtained from REST PKI, along with the parameters for the
            // signHash() call. (the page will use jQuery to decode this value)
            var response = new BatchSignatureStartResponse()
            {
                Token              = signatureParams.Token,
                ToSignHash         = Convert.ToBase64String(signatureParams.ToSignHash),
                DigestAlgorithmOid = signatureParams.DigestAlgorithmOid
            };

            return(Json(response));
        }
Beispiel #11
0
        /**
         * This action is called after the form after the user press the button "Sign". This action will
         * receive the user's CPF and current password.
         */
        public async Task <ActionResult> Authorize(string userfile, string cpf, string service, string password)
        {
            byte[] signatureContent;
            PKCertificateWithKey signingCertificate;

            try {
                // Process CPF, removing all formatting.
                var plainCpf = Regex.Replace(cpf, "/[.-]/", "");

                // Get an instance of the TrustServiceManager class, responsible for communicating with PSCs
                // and handling the OAuth flow.
                var manager = Util.GetTrustServicesManager();

                // Complete authentication using CPF and current password. The following method has three
                // sessionTypes:
                // - SINGLE_SIGNATURE: The returned token can only be used for one single signature request.
                // - MULTI_SIGNATURE: The returned token can only be used for one multi signature request.
                // - SIGNATURE_SESSION: The return token can only be used for one or more signature requests.
                var passwordAuthorizeResult = await manager.PasswordAuthorizeAsync(service, plainCpf, password, TrustServiceSessionTypes.SignatureSession);

                // Verify if the userfile exists and get its absolute path.
                string userfilePath;
                if (!StorageMock.TryGetFile(userfile, out userfilePath))
                {
                    return(HttpNotFound());
                }

                // Get an instance of the PadesSigner class, responsible for receiving the signature elements
                // and performing the local signature.
                var signer = new PadesSigner();

                // Set signature policy.
                signer.SetPolicy(GetSignaturePolicy());

                // Set file to be signed.
                signer.SetPdfToSign(userfilePath);

                // Recover the interface for the cloud certificate to be passed to PadesSigner class.
                var certificatesWithKey = await passwordAuthorizeResult.GetCertificatesWithKeyAsync();

                signingCertificate = certificatesWithKey.First();
                signer.SetSigningCertificate(signingCertificate);

                // Set a visual representation for the signature.
                signer.SetVisualRepresentation(PadesVisualElements.GetVisualRepresentationForPkiSdk(signingCertificate.Certificate));

                // Call ComputeSignature(), which does all the work, including validation of the signer's certificate and of the resulting signature
                signer.ComputeSignature();

                // Get the signed PDF as an array of bytes
                signatureContent = signer.GetPadesSignature();
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // encoding cannot be read or if the certificate is expired.
                ModelState.AddModelError("", ex.ValidationResults.ToString());
                return(View());
            }

            return(View("SignatureInfo", new SignatureInfoModel()
            {
                // Store the signature file on the folder "App_Data/".
                // With this filename, it can show a link to download the signature file.
                File = StorageMock.Store(signatureContent, ".pdf"),
                SignerCertificate = signingCertificate.Certificate
            }));
        }
Beispiel #12
0
        public async Task <ActionResult> 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 signature policy.
                SignaturePolicyId = StandardPadesSignaturePolicies.Basic,

                // Set a SecurityContext to be used to determine trust in the certificate chain. We have
                // encapsulated the security context choice on Util.cs.
                SecurityContextId = Util.GetSecurityContextId(),

                // Set a visual representation for the signature.
                VisualRepresentation = new PadesVisualRepresentation()
                {
                    // The tags {{name}} and {{national_id}} will be substituted according to the user's
                    // certificate:
                    //
                    //      name        : Full name of the signer;
                    //      national_id : If the certificate is ICP-Brasil, contains the signer's CPF.
                    //
                    // For a full list of the supported tags, see:
                    // https://github.com/LacunaSoftware/RestPkiSamples/blob/master/PadesTags.md
                    Text = new PadesVisualText("Signed by {{name}} ({{national_id}})")
                    {
                        // Specify that the signing time should also be rendered.
                        IncludeSigningTime = true,

                        // Optionally set the horizontal alignment of the text ('Left' or 'Right'), if not
                        // set the default is Left.
                        HorizontalAlign = PadesTextHorizontalAlign.Left
                    },

                    // We'll use as background the image in Content/PdfStamp.png.
                    Image = new PadesVisualImage(Util.GetPdfStampContent(), "image/png")
                    {
                        // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is
                        // completely opaque).
                        Opacity = 50,

                        // Align the image to the right
                        HorizontalAlign = PadesHorizontalAlign.Right
                    },

                    // Position of the visual representation. 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 signature positioning. Once you decide which
                    // is best for your case, you can place the code directly here.
                    Position = PadesVisualElements.GetVisualPositioning(1)
                }
            };

            // Set the document to be signed based on its ID. (passed to us from the page)
            signatureStarter.SetPdfToSign(Util.GetBatchDocPath(id));

            /*
             *                  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));

            // Call the StartWithWebPkiAsync() 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 = await signatureStarter.StartWithWebPkiAsync();

            // Notice: it is not necessary to call SetNoCacheHeaders() because this action is a POST action,
            // therefore no caching of the response will be made by browsers.

            // Return a JSON with the token obtained from REST PKI. (the page will use jQuery to decode this
            // value)
            return(Json(token));
        }