protected void Page_Load(object sender, EventArgs e) { // Get userfile from query string. var userfile = Request.QueryString["userfile"]; // Our action only works if a userfile is given to work with. if (string.IsNullOrEmpty(userfile)) { // Return "Not Found" HTTP response. Response.StatusCode = 404; Response.End(); return; } // Read document from storage. var fileContent = Storage.GetFile(userfile); // Open an validate signatures with PKI SDK based on the PAdES Basic policy. var signature = Lacuna.Pki.Pades.PadesSignature.Open(fileContent); var policyMapper = PadesPoliciesForGeneration.GetPadesBasic(Util.GetTrustArbitrator()); // Generate a model to be shown on the page from the PadesSignature instance computed from Open() // method above. This class can be inspected on SignatureModels.cs file. In this class, we validate // each signature based on the policy mapper defined above. var model = new PadesSignatureModel(signature, policyMapper); // Set property for rendering on page (see aspx file). this.Model = model; }
/// <summary> /// This method defines the signature policy that will be used on the signature. /// </summary> private ICadesPolicyMapper getSignaturePolicy() { var policy = CadesPoliciesForGeneration.GetPkiBrazilAdrBasica(); #if DEBUG // During debug only, we return a wrapper which will overwrite the policy's default trust // arbitrator (which in this case corresponds to the ICP-Brasil roots only), with our custom trust // arbitrator which accepts test certificates (see Util.GetTrustArbitrator()). return(new CadesPolicyMapperWrapper(policy, Util.GetTrustArbitrator())); #else return(policy); #endif }
/// <summary> /// This method defines the signature policy that will be used on the signature. /// </summary> private XmlPolicySpec getSignaturePolicy() { var policy = BrazilXmlPolicySpec.GetNFePadraoNacional(); #if DEBUG // During debug only, we clear the policy's default trust arbitrator (which, in the case of // the policy returned by BrazilXmlPolicySpec.GetNFePadraoNacional(), corresponds to the ICP-Brasil // roots only), and use our custom trust arbitrator which accepts test certificates // (see Util.GetTrustArbitrator()) policy.ClearTrustArbitrators(); policy.AddTrustArbitrator(Util.GetTrustArbitrator()); #endif return(policy); }
protected void Page_Load(object sender, EventArgs e) { // Get verification code from query string. var formattedVerificationCode = Request.QueryString["c"]; // On PrinterFriendlyVersion.aspx, we stored the unformatted version of the verification code // (without hyphens) but used the formatted version (with hyphens) on the printer-friendly PDF. Now, // we remove the hyphens before looking it up. var verificationCode = AlphaCode.Parse(formattedVerificationCode); // Get document associated with verification code. var fileId = Storage.LookupVerificationCode(verificationCode); if (fileId == null) { // Invalid code given! // Small delay to slow down brute-force attacks (if you want to be extra careful you might want // to add a CAPTCHA to the process). Thread.Sleep(TimeSpan.FromSeconds(2)); // Return "Not Found" HTTP response. Response.StatusCode = 404; Response.End(); return; } // Read document from storage. var fileContent = Storage.GetFile(fileId); // Open and validate signatures with PKI SDK based on the PAdES Basic policy. var signature = Lacuna.Pki.Pades.PadesSignature.Open(fileContent); var policyMapper = PadesPoliciesForGeneration.GetPadesBasic(Util.GetTrustArbitrator()); // Generate a model to be shown on the page from the PadesSignature instance computed from Open() // method above. This class can be inspected on SignatureModels.cs file. In this class, we validate // each signature based on the policy mapper defined above. var model = new PadesSignatureModel(signature, policyMapper); // Set properties for rendering on page (see aspx file). this.FileId = fileId; this.Model = model; }
protected void SubmitButton_Click(object sender, EventArgs e) { var nonceStore = Util.GetNonceStore(); var certAuth = new PKCertificateAuthentication(nonceStore); PKCertificate certificate; var vr = certAuth.Complete(Convert.FromBase64String(NonceField.Value), Convert.FromBase64String(CertificateField.Value), Convert.FromBase64String(SignatureField.Value), Util.GetTrustArbitrator(), out certificate); if (!vr.IsValid) { vr.Errors.ForEach(ve => ModelState.AddModelError("", ve.ToString())); startNewAuth(); return; } this.AuthenticatedCertificate = certificate; this.ValidationResults = vr; Server.Transfer("AuthenticationSuccess.aspx"); }
/// <summary> /// This method defines the signature policy that will be used on the signature. /// </summary> private IPadesPolicyMapper getSignaturePolicy() { return(PadesPoliciesForGeneration.GetPadesBasic(Util.GetTrustArbitrator())); }
private byte[] generatePrinterFriendlyVersion(byte[] pdfContent, string verificationCode) { // The verification code is generated without hyphens to save storage space and avoid copy-and-paste // problems. On the PDF generation, we use the "formatted" version, with hyphens (which will later // be discarded on the verification page). var formattedVerificationCode = AlphaCode.Format(verificationCode); // Build the verification link from the constant "VerificationLinkFormat" (see above) and the // formatted verification code. var verificationLink = string.Format(VerificationLinkFormat, formattedVerificationCode); // 1. Inspect signatures on the PDF. var signature = Lacuna.Pki.Pades.PadesSignature.Open(pdfContent); // 2. Create PDF with verification information from the signed PDF. var pdfMarker = new PdfMarker(); // Build string with joined names of signers (see method getDisplayName() below). var signerNames = Util.JoinStringsPt(signature.Signers.Select(s => getDisplayName(s.Signer.SigningCertificate))); var allPagesMessage = string.Format("This document was digitally signed by {0}.\nTo verify the signatures go to {1} on {2} and inform the code {3}", signerNames, VerificationSiteNameWithArticle, VerificationSite, formattedVerificationCode); // ICP-Brasil logo on bottom-right corner of every page (except on the page which will be created at // the end of the document). pdfMarker.AddMark(new PdfMark() { PageOption = PdfMarkPageOptions.AllPages, Container = new PadesVisualRectangle() { Width = 1, Right = 1, Height = 1, Bottom = 1 }, Elements = new List <PdfMarkElement>() { new PdfMarkImage() { ImageContent = Storage.GetIcpBrasilLogoContent(), Opacity = 75 } } }); // Summary on bottom margin of every page (except on the page which will be created at the end of // the document). pdfMarker.AddMark(new PdfMark() { PageOption = PdfMarkPageOptions.AllPages, Container = new PadesVisualRectangle() { Height = 2, Bottom = 0, Left = 1.5, Right = 3.5 }, Elements = new List <PdfMarkElement>() { new PdfMarkText() { Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, Text = allPagesMessage } } } } }); // Summary on right margin of every page (except on the page which will be created at the end of the // document), rotated 90 degrees counterclockwise (text goes up). pdfMarker.AddMark(new PdfMark() { PageOption = PdfMarkPageOptions.AllPages, Container = new PadesVisualRectangle() { Width = 2, Right = 0, Top = 1.5, Bottom = 3.5 }, Elements = new List <PdfMarkElement>() { new PdfMarkText() { Rotation = PdfMarkRotation.D90, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, Text = allPagesMessage } } } } }); // Create a "manifest" mark on a new page added on the end of the document. We'll add several // elements to this marks. var manifestMark = new PdfMark() { PageOption = PdfMarkPageOptions.NewPage, // This mark's container is the whole page with 1-inch margins. Container = new PadesVisualRectangle() { Top = 2.54, Bottom = 2.54, Right = 2.54, Left = 2.54 } }; // We'll keep track of our "vertical offset" as we add elements to the mark. double verticalOffset = 0; double elementHeight; elementHeight = 3; // ICP-Brasil logo on the upper-left corner. manifestMark.Elements.Add(new PdfMarkImage() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Width = elementHeight, /* Using elemengHeight as width because the image is square. */ Left = 0 }, ImageContent = Storage.GetIcpBrasilLogoContent() }); // QR Code with the verification link on the upper-right corner. We will generate a PdfMarkImage from // a QR Code generated using the QRCoder library. byte[] qrCodeImageContent; using (var qrGenerator = new QRCodeGenerator()) { using (var qrCodeData = qrGenerator.CreateQrCode(verificationLink, QRCodeGenerator.ECCLevel.M)) { using (var qrCode = new QRCode(qrCodeData)) { var qrCodeBitmap = qrCode.GetGraphic(10, Color.Black, Color.White, false); using (var buffer = new MemoryStream()) { qrCodeBitmap.Save(buffer, ImageFormat.Png); qrCodeImageContent = buffer.ToArray(); }; } } } manifestMark.Elements.Add(new PdfMarkImage() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Width = elementHeight, /* Using elemengHeight as width because the image is square. */ Right = 0 }, ImageContent = qrCodeImageContent }); // Header "SIGNATURES VERIFICATION" centered between ICP-Brasil logo and QR Code. manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset + 0.2, Right = 0, Left = 0 }, Align = PadesHorizontalAlign.Center, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize * 1.6, Text = "SIGNATURES\nVERIFICATION" } } }); verticalOffset += elementHeight; // Verifical padding. verticalOffset += 1.7; // Header with verification code. elementHeight = 2; manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Right = 0, Left = 0 }, Align = PadesHorizontalAlign.Center, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize * 1.2, Text = string.Format("Verification Code: {0}", formattedVerificationCode) } } }); verticalOffset += elementHeight; // Paragraph saying "this document was signed by the following signer etc" and mentioning the time zone of the // date/times below. elementHeight = 2.5; manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Left = 0, Right = 0 }, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = string.Format("This document was digitally signed by the following signers on the indicated dates ({0}):", TimeZoneDisplayName) } } }); verticalOffset += elementHeight; // Iterate signers. foreach (var signer in signature.Signers) { elementHeight = 1.5; // Validate signature based on the PAdES Basic policy. var policyMapper = PadesPoliciesForGeneration.GetPadesBasic(Util.GetTrustArbitrator()); var validationResults = signature.ValidateSignature(signer, policyMapper); // Green "check" or red "X" icon depending on result of validation for this signer. manifestMark.Elements.Add(new PdfMarkImage() { RelativeContainer = new PadesVisualRectangle() { Height = 0.5, Top = verticalOffset + 0.2, Width = 0.5, Left = 0 }, ImageContent = Storage.GetValidationResultIcon(validationResults.IsValid) }); // Description of signer (see method getSignerDescription() below). manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Left = 0.8, Right = 0 }, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = getSignerDescription(signer) } } }); verticalOffset += elementHeight; } // Some vertical padding from last signer. verticalOffset += 1; // Paragraph with link to veritifcation site and citing both the verification code above and the // verification link below. elementHeight = 2.5; manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Right = 0, Left = 0 }, Texts = new List <PdfTextSection>() { new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = string.Format("To verify the signatures, go to {0} on ", VerificationSiteNameWithArticle) }, new PdfTextSection() { Color = Color.Blue, Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = VerificationSite }, new PdfTextSection() { Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = " and inform the code above or follow the link below:" } } }); verticalOffset += elementHeight; // Verification link. elementHeight = 1.5; manifestMark.Elements.Add(new PdfMarkText() { RelativeContainer = new PadesVisualRectangle() { Height = elementHeight, Top = verticalOffset, Right = 0, Left = 0 }, Align = PadesHorizontalAlign.Center, Texts = new List <PdfTextSection>() { new PdfTextSection() { Color = Color.Blue, Style = PdfTextStyle.Normal, FontSize = NormalFontSize, Text = verificationLink } } }); pdfMarker.AddMark(manifestMark); // Prevent from throwing exception when the file to be marked already have a signature (default: true). pdfMarker.ThrowIfSignedPdf = false; // Note: Before applying the marks, all signature from the signed file will be removed. // Apply marks and return the printer-friendly PDF's content. byte[] pfvContent = pdfMarker.WriteMarks(pdfContent); return(pfvContent); }