public ActionResult Index(SignatureStartModel model) { byte[] toSignHash, transferData; SignatureAlgorithm signatureAlg; try { // Instantiate a CadesSigner class var signer = new XmlElementSigner(); // Set the data to sign, which in the case of this example is a fixed sample "COD envelope" signer.SetXml(StorageMock.GetSampleCodEnvelopeContent()); // Set the ID of the COD element signer.SetToSignElementId("COD"); // Decode the user's certificate and set as the signer certificate signer.SetSigningCertificate(PKCertificate.Decode(model.CertContent)); // Set the signature policy signer.SetPolicy(getSignaturePolicy()); // Generate the "to-sign-hash". This method also yields the signature algorithm that must // be used on the client-side, based on the signature policy. toSignHash = signer.GenerateToSignHash(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 (SignCodComplete action), we'll need once again some information: // - The thumpprint of the selected certificate // - The "to-sign-hash" // - The OID of the digest algorithm to be used during the signature operation // - 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. TempData["SignatureCompleteModel"] = new SignatureCompleteModel() { CertThumb = model.CertThumb, ToSignHash = toSignHash, DigestAlgorithmOid = signatureAlg.DigestAlgorithm.Oid, TransferDataFileId = StorageMock.Store(transferData, ".bin"), }; return(RedirectToAction("Complete")); }
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 XmlElementSigner class. var signer = new XmlElementSigner(); // Set the document to be signed and the policy, exactly like in the SignCod method. signer.SetXml(StorageMock.GetSampleCodEnvelopeContent()); signer.SetPolicy(getSignaturePolicy()); // Set the signature computed on the client-side, along with the "transfer data" signer.SetPrecomputedSignature(model.Signature, transferDataContent); // Call ComputeSignature(), which validates the signature of the "to-sign-hash" and finishes the signature process signer.ComputeSignature(); // Get the signed XML as an array of bytes signatureContent = signer.GetSignedXml(); } 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. // 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 redirect to the SignatureInfo action with the filename. File = StorageMock.Store(signatureContent, ".xml") }; return(RedirectToAction("SignatureInfo")); }
// GET CodXmlSignature public async Task <ActionResult> Index() { // Instantiate the XmlElementSignatureStarter class, responsible for receiving the signature // elements and start the signature process. var signatureStarter = new XmlElementSignatureStarter(Util.GetRestPkiClient()); // Set the data to sign, which in the case of this example is a fixed sample "COD envelope" signatureStarter.SetXml(StorageMock.GetSampleCodEnvelopeContent()); // Set the ID of the COD element signatureStarter.SetToSignElementId("COD"); // Set the signature policy signatureStarter.SetSignaturePolicy(StandardXmlSignaturePolicies.CodSha1); // Set the security context to be used to determine trust in the certificate chain. We have // encapsulated the security context choice on Util.cs. signatureStarter.SetSecurityContext(Util.GetSecurityContextId()); // Call the StartWithWebPki() method, which initiates the signature. This yields the token, // a 43-character case-sensitive URL-safe string, which identifies this signature process. We'll // use this value to call the signWithRestPki() method on the Web PKI component (see // 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(); // 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 })); }
public ActionResult SampleCodEnvelope() { var fileContent = StorageMock.GetSampleCodEnvelopeContent(); return(File(fileContent, "text/xml", "SampleCodEnvelope.xml")); }