public ActionResult Complete(BatchSignatureCompleteRequest request)
        {
            byte[] signatureContent;

            // Recover the "transfer data" content stored in a temporary file.
            byte[] transferDataContent;
            if (!StorageMock.TryGetFile(request.TransferDataFileId, out transferDataContent))
            {
                return(HttpNotFound());
            }

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

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

            // Set the signature computed on the client-side, along with the "transfer data" recovered from a temporary file
            padesSigner.SetPreComputedSignature(request.Signature, transferDataContent);

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

            // Get the signed PDF as an array of bytes
            signatureContent = padesSigner.GetPadesSignature();

            return(Json(new BatchSignatureCompleteResponse()
            {
                SignedFileId = StorageMock.Store(signatureContent, ".pdf")
            }));
        }
        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 IHttpActionResult Start(SignatureStartRequest request)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

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

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

                // Set the PDF to sign, which in the case of this example is a fixed sample document
                if (!string.IsNullOrEmpty(request.FileId))
                {
                    padesSigner.SetPdfToSign(Storage.GetFile(request.FileId));
                }
                else
                {
                    padesSigner.SetPdfToSign(Storage.GetSampleDocContent());
                }

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

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

                // Set the signature's visual representation options (optional)
                padesSigner.SetVisualRepresentation(getVisualRepresentation(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 ResponseMessageResult(Request.CreateResponse(HttpStatusCode.BadRequest, new ValidationErrorModel(ex.ValidationResults))));
            }

            // Create response with some informations that we'll use on Complete action and on client-side.
            var response = new SignatureStartResponse()
            {
                // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we mustn't use a hidden field
                // on the page to store it. Here we're using our storage mock (see file Classes\Storage.cs) to simulate storing the transfer data
                // on a database and saving on a hidden field on the page only the ID that can be used later to retrieve it. Another option would
                // be to store the transfer data on the Session dictionary.
                TransferDataFileId = Storage.StoreFile(transferData),

                // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the digest algorithm that must
                // be used on the signature algorithm computation
                ToSignBytes        = toSignBytes,
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            };

            return(Ok(response));
        }
        private void completeSignature()
        {
            byte[] signatureContent;

            try {
                // Retrieve the "transfer data" stored on the initial step (see method startNextSignature()).
                var transferData = Storage.GetFile(TransferDataFileIdField.Value);

                // We won't be needing the "transfer data" anymore, so we delete it.
                Storage.DeleteFile(TransferDataFileIdField.Value);

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

                // Set the signature policy, exactly like in the Start method.
                padesSigner.SetPolicy(getSignaturePolicy());

                // Set the signature computed on the client-side, along with the "transfer data".
                padesSigner.SetPreComputedSignature(Convert.FromBase64String(SignatureField.Value), transferData);

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

                // Get the signed PDF as an array of bytes.
                signatureContent = padesSigner.GetPadesSignature();
            }
            catch (ValidationException ex) {
                // One or more validations failed. We log the error and update the page with a summary of what
                // happened to this document.
                logger.Error(ex, "Validation error completing the signature of a batch document");
                setValidationError(ex.ValidationResults);
                return;
            }
            catch (Exception ex) {
                // An error has occurred. We log the error and update the page with a summary of what happened to
                // this document.
                logger.Error(ex, "Error completing the signature of a batch document");
                setError(ex.Message);
                return;
            }

            // Store the signed file.
            var file = Storage.StoreFile(signatureContent, ".pdf");

            // Update the page with a link to the signed file.
            var docItem = DocumentsListView.Items[DocumentIndex];

            docItem.DataItem = new DocumentItem()
            {
                Id           = DocumentIds[DocumentIndex],
                DownloadLink = "Download?file=" + file
            };
            docItem.DataBind();
        }
        // GET: PadesServerKeySdk
        public ActionResult Index(string userfile)
        {
            byte[] signatureContent;
            PKCertificateWithKey certWithKey;

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

                // Verify if the userfile exists and get the content of the userfile.
                if (!StorageMock.TryGetFile(userfile, out byte[] userfileContent))
Пример #6
0
        static void Main(string[] args)
        {
            // This is a TRIAL token. It will expire at 31/08/2020.
            PkiConfig.LoadLicense(Convert.FromBase64String("AxAAIIy8jc59Q0q95BZrL57K5hEAUEtJIFN1aXRlIFNhbXBsZXMIAAD0Ze31HdgICACAXwryrU7YCAAAAAAAAAQAfwAAAAABL2+ls7EW5LHD/tEetd49d0JpmU7pXEjhH0pU1ZSp5qjvKxL8c8PZz6ODTf68+lfQtXkKaRlQH6hu7VTSU3fvhCmZovDB5ruKqJPn+MQRDBbS8Wkr/meVo9LBS+3NFOky+EY43ebFoFxTbVZl2lCjb0DuskJiZGuHOBJ1v2XpGdKCmh1c1LmMvpc+OPegzNuMCXoEzSN9DdRtKnDzRxvOnvPglCX9+oV89LWsmVzonRp1a+tluqa8Ron9pFdHI9cWBElcXpmwXbKbmP0Sy5yYbYpE+rYsNgD5sV/FwF8uOxGWA0/mRWLZlO3OcGWoYo7qBBDmCUApAcRmZR3tXqhELQ=="));

            var connection = new ConnectionBuilder()
                             .WithLogging()
                             .Build();

            // "List Certificates" operation.
            connection.On <string, List <CertificateModel> >("list-certs", _ => {
                var store = WindowsCertificateStore.LoadPersonalCurrentUser();

                return(store.GetCertificatesWithKey().Select(c => new CertificateModel(c.Certificate)).ToList());
            });

            // "Sign a PDF" operation.
            connection.On <SignatureRequestModel, string>("sign-pdf", request => {
                var signer = new PadesSigner();

                var store       = WindowsCertificateStore.LoadPersonalCurrentUser();
                var signingCert = store.GetCertificatesWithKey().First(c => c.Certificate.ThumbprintSHA256.SequenceEqual(request.CertThumb));

                signer.SetSigningCertificate(signingCert);
                signer.SetPdfToSign(request.FileToSign);

                var trustArbitrator = new LinkedTrustArbitrator(TrustArbitrators.PkiBrazil, TrustArbitrators.Windows);
                // For development purposes, we also trust in Lacuna Software's test certificates.
                var lacunaRoot = Lacuna.Pki.PKCertificate.Decode(Convert.FromBase64String("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"));
                // COMMENT the line below before production release
                trustArbitrator.Add(new TrustedRoots(lacunaRoot));

                signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(trustArbitrator));
                signer.ComputeSignature();

                byte[] signedPdf = signer.GetPadesSignature();

                var tempLocation = Path.GetTempFileName();
                File.WriteAllBytes(tempLocation, signedPdf);

                return(tempLocation);
            });

            // Acknowledges that the connection is running.
            connection.On <string, string>("ping", argument => "pong");


            // wait for incoming requests
            connection.Listen();
        }
Пример #7
0
        protected void SubmitCertificateButton_Click(object sender, EventArgs e)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

            try {
                // Decode the user's certificate.
                var cert = PKCertificate.Decode(Convert.FromBase64String(CertificateField.Value));

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

                // Set the PDF to sign, which in the case of this example is a fixed sample document.
                padesSigner.SetPdfToSign(Storage.GetSampleDocContent());

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

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

                // Set the signature's visual representation options (optional).
                padesSigner.SetVisualRepresentation(getVisualRepresentation(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.
                ex.ValidationResults.Errors.ForEach(ve => ModelState.AddModelError("", ve.ToString()));
                return;
            }

            // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we
            // mustn't use a hidden field on the page to store it. Here we're using our storage mock
            // (see file Classes\Storage.cs) to simulate storing the transfer data on a database and saving on a
            // hidden field on the page only the ID that can be used later to retrieve it. Another option would
            // be to store the transfer data on the Session dictionary.
            TransferDataFileIdField.Value = Storage.StoreFile(transferData);

            // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the
            // digest algorithm that must be used on the signature algorithm computation.
            ToSignHashField.Value      = Convert.ToBase64String(signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes));
            DigestAlgorithmField.Value = signatureAlg.DigestAlgorithm.Oid;
        }
        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
            }));
        }
        public ActionResult Complete(SignatureCompleteModel model)
        {
            byte[] signatureContent;

            try {
                // Recover the "transfer data" content stored in a temporary file.
                byte[] transferDataContent;
                if (!StorageMock.TryGetFile(model.TransferDataFileId, out transferDataContent))
                {
                    return(HttpNotFound());
                }

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

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

                // Set the signature computed on the client-side, along with the "transfer data" (rendered in a hidden field, see the view)
                padesSigner.SetPreComputedSignature(model.Signature, transferDataContent);

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

                // Get the signed PDF as an array of bytes
                signatureContent = padesSigner.GetPadesSignature();
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate is revoked.
                ModelState.AddModelError("", ex.ValidationResults.ToString());
                // Return userfile to continue the signature with the same file.
                return(View(model));
            }

            // On the next step (SignatureInfo action), we'll render the following information:
            // - The filename to be available to download in next action.
            // - The signer's certificate information to be rendered.
            // We'll store these values on TempData, which is a dictionary shared between actions.
            TempData["SignatureInfoModel"] = new SignatureInfoModel()
            {
                // Store the signature file on the folder "App_Data/" and redirects to the SignatureInfo action with the filename.
                // With this filename, it can show a link to download the signature file.
                File = StorageMock.Store(signatureContent, ".pdf")
            };

            return(RedirectToAction("SignatureInfo"));
        }
Пример #10
0
        protected void SubmitSignatureButton_Click(object sender, EventArgs e)
        {
            byte[] signatureContent;

            try {
                // Retrieve the "transfer data" stored on the initial step (see method startNextSignature()).
                var transferData = Storage.GetFile(TransferDataFileIdField.Value);

                // We won't be needing the "transfer data" anymore, so we delete it.
                Storage.DeleteFile(TransferDataFileIdField.Value);

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

                // Set the signature policy, exactly like in the Start method.
                padesSigner.SetPolicy(getSignaturePolicy());

                // Set the signature computed on the client-side, along with the "transfer data".
                padesSigner.SetPreComputedSignature(Convert.FromBase64String(SignatureField.Value), transferData);

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

                // Get the signed PDF as an array of bytes.
                signatureContent = padesSigner.GetPadesSignature();
            }
            catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate
                // is revoked.
                ex.ValidationResults.Errors.ForEach(ve => ModelState.AddModelError("", ve.ToString()));
                CertificateField.Value = "";
                ToSignHashField.Value  = "";
                return;
            }

            // Pass the following fields to be used on PadesSignatureInfo page:
            // - The signature file will be stored on the folder "App_Data/". Its name will be passed by
            //   SignatureFile field.
            // - The user's certificate
            this.SignatureFile = Storage.StoreFile(signatureContent, ".pdf");
            this.Certificate   = PKCertificate.Decode(Convert.FromBase64String(CertificateField.Value));

            Server.Transfer("PadesSignatureInfo.aspx");
        }
Пример #11
0
        public void Sign()
        {
            if (string.IsNullOrEmpty(PdfPath))
            {
                MessageBox.Show("Please choose a PDF file sign");
                return;
            }
            if (!File.Exists(PdfPath))
            {
                MessageBox.Show("File not found: " + PdfPath);
                return;
            }
            if (SelectedCertificate == null)
            {
                MessageBox.Show("Please choose a certificate to sign the PDF");
                return;
            }
            if (Width <= 0 || Height <= 0 || Bottom <= 0 || Left <= 0)
            {
                MessageBox.Show("Please fill all coordinates with positive numbers");
                return;
            }

            try {
                var signer = new PadesSigner();                                                                              // Instantiate the PDF signer
                signer.SetSigningCertificate(selectedCertificate.CertificateWithKey);                                        // certificate with private key associated
                signer.SetPdfToSign(PdfPath);                                                                                // PDF file path
                signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(App.GetTrustArbitrator()));                        // Basic signature policy with the selected trust arbitrator
                signer.SetVisualRepresentation(getVisualRepresentation(selectedCertificate.CertificateWithKey.Certificate)); // Signature visual representation
                signer.ComputeSignature();                                                                                   // computes the signature
                byte[] signedPdf = signer.GetPadesSignature();                                                               // return the signed PDF bytes

                // saving signed PDF file
                var savePath = getSaveFilePath();
                if (!string.IsNullOrEmpty(savePath))
                {
                    File.WriteAllBytes(savePath, signedPdf);
                    Process.Start(savePath);
                }
            } catch (ValidationException ex) {
                new ValidationResultsDialog("Validation failed", ex.ValidationResults).ShowDialog();
            } catch (Exception ex) {
                MessageBox.Show($"Error while signing PDF\r\n\r\n{ex}");
            }
        }
        public IHttpActionResult Complete(SignatureCompleteRequest request)
        {
            byte[] signatureContent;

            try {
                // Retrieve the "transfer data" stored on the initial step (see Start action)
                var transferData = Storage.GetFile(request.TransferDataFileId);

                // We won't be needing the "transfer data" anymore, so we delte it
                Storage.DeleteFile(request.TransferDataFileId);

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

                // Set the signature policy, exactly like in the Start method
                padesSigner.SetPolicy(getSignaturePolicy());

                // Set the signature computed on the client-side, along with the "transfer data"
                padesSigner.SetPreComputedSignature(request.Signature, transferData);

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

                // Get the signed PDF as an array of bytes
                signatureContent = padesSigner.GetPadesSignature();
            } catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate is revoked.
                return(new ResponseMessageResult(Request.CreateResponse(HttpStatusCode.BadRequest, new ValidationErrorModel(ex.ValidationResults))));
            }

            // Pass the following fields to be used on signature-results template:
            // - The signature file will be stored on the folder "App_Data/". Its name will be passed by Filename field.
            // - The user's certificate
            var response = new SignatureCompleteResponse()
            {
                Filename    = Storage.StoreFile(signatureContent, ".pdf"),
                Certificate = new CertificateModel(PKCertificate.Decode(request.Certificate))
            };

            return(Ok(response));
        }
Пример #13
0
        public IHttpActionResult Complete(BatchSignatureCompleteRequest request)
        {
            byte[] signatureContent;

            try {
                // Recover the "transfer data" content stored in a temporary file
                string extension;
                byte[] transferDataContent;
                if (!Storage.TryGetFile(request.TransferDataFileId, out transferDataContent, out extension))
                {
                    return(NotFound());
                }

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

                // Set the signature policy, exactly like in the Start method
                padesSigner.SetPolicy(getSignaturePolicy());

                // Set the signature computed on the client-side, along with the "transfer data" recovered from a temporary file
                padesSigner.SetPreComputedSignature(request.Signature, transferDataContent);

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

                // Get the signed PDF as an array of bytes
                signatureContent = padesSigner.GetPadesSignature();
            }
            catch (ValidationException ex) {
                // Some of the operations above may throw a ValidationException, for instance if the certificate is revoked.
                var message = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ValidationResults.ToString());
                return(ResponseMessage(message));
            }

            return(Ok(new BatchSignatureCompleteResponse()
            {
                SignedFileId = Storage.StoreFile(signatureContent, ".pdf")
            }));
        }
        public ActionResult Complete(SignatureCompleteModel model)
        {
            byte[] signatureContent;

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

                // Set the signature policy, exactly like in the Start method
                padesSigner.SetPolicy(getSignaturePolicy());

                // Set the signature computed on the client-side, along with the "transfer data" (rendered in a hidden field, see the view)
                padesSigner.SetPreComputedSignature(model.Signature, model.TransferData);

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

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

            // On the next step (SignatureInfo action), we'll render the following information:]
            // - The filename to be available to download in next action.
            // - The signer's certificate information to be rendered.
            // We'll store these values on TempData, which is a dictionary shared between actions.
            TempData["SignatureInfoModel"] = new SignatureInfoModel()
            {
                // Store the signature file on the folder "App_Data/" and redirects to the SignatureInfo action with the filename.
                // With this filename, it can show a link to download the signature file.
                Filename = Storage.StoreFile(signatureContent, ".pdf"),
                UserCert = PKCertificate.Decode(model.CertContent)
            };

            return(RedirectToAction("SignatureInfo"));
        }
Пример #15
0
        private static bool SignFile(string file, PKCertificateWithKey certWithKey, PadesPolicySpec policy, PadesVisualRepresentation2 visual, Metadata metadata, string outputDir, string outputName = null)
        {
            var documentoToSign = File.ReadAllBytes(file);

            if (metadata != null)
            {
                using (var buffer = new MemoryStream())
                {
                    using (var stream = new MemoryStream(documentoToSign))
                    {
                        DoConvertToPdfA(stream, metadata, buffer);
                    }
                    documentoToSign = buffer.ToArray();
                }
            }

            var signer = new PadesSigner();

            signer.SetSigningCertificate(certWithKey);
            signer.SetPdfToSign(documentoToSign);
            signer.SetPolicy(policy);
            signer.SetVisualRepresentation(visual);
            signer.SetCertificateValidationConfigurator(ConfigureNoValidation);
            if (string.IsNullOrWhiteSpace(outputName))
            {
                outputName = Path.GetFileName(file);
            }
            try {
                signer.ComputeSignature();
                var signed = signer.GetPadesSignature();
                File.WriteAllBytes(Path.Combine(outputDir, outputName), signed);
            } catch (Exception exception) {
                Log(exception.ToString(), file);
                return(false);
            }
            return(true);
        }
        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("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"));
                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 }));
        }
Пример #17
0
        public IHttpActionResult 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(Storage.GetBatchDocContent(request.Id));

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

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

                // Set the signature's visual representation options (this is optional). For more information, see
                // http://pki.lacunasoftware.com/Help/html/98095ec7-2742-4d1f-9709-681c684eb13b.htm
                var visual = new PadesVisualRepresentation2()
                {
                    // Text of the visual representation
                    Text = new PadesVisualText()
                    {
                        // Compose the message
                        CustomText = $"Assinado digitalmente por {cert.SubjectDisplayName}",

                        // 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
                    },
                    // Background image of the visual representation
                    Image = new PadesVisualImage()
                    {
                        // We'll use as background the image in Content/PdfStamp.png
                        Content = Storage.GetPdfStampContent(),

                        // 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
                    },
                    // Set the position of the visual representation
                    Position = PadesVisualAutoPositioning.GetFootnote()
                };
                padesSigner.SetVisualRepresentation(visual);

                // 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.
                var message = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ValidationResults.ToString());
                return(ResponseMessage(message));
            }

            // 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(Ok(new BatchSignatureStartResponse()
            {
                TransferDataFileId = Storage.StoreFile(transferData, ".bin"),
                ToSignHash = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes),
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            }));
        }
Пример #18
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
            }));
        }
        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
            // "ToSignHashField" 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)
            {
                ToSignHashField.Value = "(end)";
                return;
            }

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

            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

            try {
                // Decode the user's certificate.
                var cert = PKCertificate.Decode(Convert.FromBase64String(CertificateField.Value));

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

                // Set the PDF to sign.
                padesSigner.SetPdfToSign(Storage.GetBatchDocContent(docId));

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

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

                // Set the signature's visual representation options (optional).
                padesSigner.SetVisualRepresentation(getVisualRepresentation(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) {
                // 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.
                logger.Error(ex, "Validation error starting the signature of a batch document");
                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.
                logger.Error(ex, "Error starting the signature of a batch document");
                setError(ex.Message);
                startNextSignature();
                return;
            }

            // The "transfer data" for PDF signatures can be as large as the original PDF itself. Therefore, we
            // mustn't use a hidden field on the page to store it. Here we're using our storage mock
            // (see file Classes\Storage.cs) to simulate storing the transfer data on a database and saving on a
            // hidden field on the page only the ID that can be used later to retrieve it. Another option would
            // be to store the transfer data on the Session dictionary.
            TransferDataFileIdField.Value = Storage.StoreFile(transferData);

            // Send to the javascript the "to sign hash" of the document (digest of the "to-sign-bytes") and the
            // digest algorithm that must be used on the signature algorithm computation
            ToSignHashField.Value      = Convert.ToBase64String(signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes));
            DigestAlgorithmField.Value = signatureAlg.DigestAlgorithm.Oid;
        }
Пример #20
0
        public async Task <IActionResult> Post([FromBody] SignatureRequest request)
        {
            // 1. Retrieve key using certId stored on your database.
            byte[] pkcs12;
            try {
                pkcs12 = await _azureKeyVaultStore.GetPkcs12Async(request.CertId);
            } catch (InvalidIdentifierException ex) {
                return(UnprocessableEntity(new ErrorModel()
                {
                    Code = ErrorCodes.InvalidIdentifier,
                    Message = ex.Message,
                }));
            }

            // 2. Open PKCS#12, verifying valid of the provided password.
            Pkcs12CertificateStore store;

            try {
                store = Pkcs12CertificateStore.Load(pkcs12, request.Pkcs12Password);
            } catch (IncorrectPinException ex) {
                return(UnprocessableEntity(new ErrorModel()
                {
                    Code = ErrorCodes.InvalidPIN,
                    Message = ex.Message,
                }));
            }

            // 3. Retrieve certification info (include its key).
            var certs = store.GetCertificatesWithKey();

            if (!certs.Any())
            {
                return(UnprocessableEntity(new ErrorModel()
                {
                    Code = ErrorCodes.InvalidPkcs12,
                    Message = "The provided PKCS#12 file is not valid",
                }));
            }
            var cert = certs.First();

            // 4. Perform signature.
            var signer = new PadesSigner();

            signer.SetSigningCertificate(cert);
            signer.SetPdfToSign(Path.Combine(_webHostEnvironment.ContentRootPath, "Resources", "SamplePdf.pdf"));
            signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic());
            signer.SetVisualRepresentation(GetVisualRepresentation(cert.Certificate));
            signer.ComputeSignature();
            byte[] signedPdf = signer.GetPadesSignature();

            // 5. Store signature file.
            if (!System.IO.File.Exists(Path.Combine(_webHostEnvironment.ContentRootPath, "App_Data")))
            {
                Directory.CreateDirectory(Path.Combine(_webHostEnvironment.ContentRootPath, "App_Data"));
            }
            var fileId = Guid.NewGuid() + ".pdf";

            System.IO.File.WriteAllBytes(Path.Combine(_webHostEnvironment.ContentRootPath, "App_Data", fileId), signedPdf);

            return(Ok(new SignatureResponse()
            {
                FileId = fileId,
            }));
        }
        public ActionResult Index(SignatureStartModel model)
        {
            byte[]             toSignBytes, transferData;
            SignatureAlgorithm signatureAlg;

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

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

                // Set the PDF to sign, which in the case of this example is a fixed sample document
                padesSigner.SetPdfToSign(Storage.GetSampleDocContent());

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

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

                // Set the signature's visual representation options (this is optional). For more information, see
                // http://pki.lacunasoftware.com/Help/html/98095ec7-2742-4d1f-9709-681c684eb13b.htm
                var visual = new PadesVisualRepresentation2()
                {
                    // Text of the visual representation
                    Text = new PadesVisualText()
                    {
                        // Compose the message
                        CustomText = String.Format("Assinado digitalmente por {0}", cert.SubjectDisplayName),

                        // 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
                    },
                    // Background image of the visual representation
                    Image = new PadesVisualImage()
                    {
                        // We'll use as background the image in Content/PdfStamp.png
                        Content = Storage.GetPdfStampContent(),

                        // 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
                    },
                    // Set the position of the visual representation
                    Position = PadesVisualAutoPositioning.GetFootnote()
                };
                padesSigner.SetVisualRepresentation(visual);

                // 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 content of the selected certificate only used to render the user's certificate information
            //  after the signature is completed. It is no longer needed for the signature process.
            // - The thumbprint of the selected certificate.
            // - The "transfer data" used to validate the signature in 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()
            {
                CertContent        = model.CertContent,
                CertThumb          = model.CertThumb,
                TransferData       = transferData,
                ToSignHash         = signatureAlg.DigestAlgorithm.ComputeHash(toSignBytes),
                DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid
            };

            return(RedirectToAction("Complete"));
        }
Пример #22
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
            }));
        }