// This function is called by the Pades Signature Starter action (see PadesSignatureController.cs). // It contains examples of PDF marks, isual elements of arbitrary content placed in every page. public static PdfMark GetPdfMark(int sampleNumber) { switch (sampleNumber) { case 1: // Example #1: A sample text and image are placed at the bottom of every page. // First, we create the mark object. It contains no elements, being a simple empty box. var mark = new PdfMark() { // Here, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying the width (but no left nor right) results in a horizontally centered fixed-width container Width = 8, // Specifying bottom and height (but no top) results in a bottom-aligned fixed-height container Bottom = 0.2, Height = 0.6 } // This example has no background and no borders, so we don't set BackgroundColor nor BorderColor }; // First, the image. mark.Elements.Add(new PdfMarkImageElement() { // We'll position it to the right of the text. RelativeContainer = new PadesVisualRectangle() { // Specifying right and width (but no left) results in a right-aligned fixed-width container Right = 0, Width = 1, // Specifying top and bottom (but no height) results in a variable-height container with the given margins Top = 0, Bottom = 0 }, // We'll use the image at 'Content/PdfStamp.png'. Image = new PdfMarkImage(Util.GetPdfStampContent(), "image/png") { // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque). Opacity = 75, } }); // Then, the text. mark.Elements.Add(new PdfMarkTextElement() { // We center the text. RelativeContainer = new PadesVisualRectangle() { // Specifying left and right (but no width) results in a variable-width container with the given margins Left = 1, Right = 0, // Specifying just the height results in a vertically centered fixed-height container Height = 0.5 }, // Then add the text sections. TextSections = { // First, a simple message. new PdfTextSection() { // We set the text. Text = "This document was digitally signed with ", // Its color. Color = Color.Black, // Its size. FontSize = 8, // And the style. Style = PdfTextStyle.Normal }, // And a bold ending. new PdfTextSection() { // We set the text. Text = "RestPKI", // Its color. Color = Color.Black, // Its size. FontSize = 8, // And the style. Style = PdfTextStyle.Bold } } }); return(mark); case 2: // Example #2: An image will be placed at the bottom of every page. // First, we create the mark object. It contains no elements, being a simple empty box. mark = new PdfMark() { // Then, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying right and width (but no left) results in a right-aligned fixed-width container Right = 1, Width = 2.54, // Specifying bottom and height (but no top) results in a bottom-aligned fixed-height container Bottom = 1, Height = 2.54 }, // After that, its border must be configured. BorderWidth = 0.02, BorderColor = Color.Black }; // Add a single image element mark.Elements.Add(new PdfMarkImageElement() { // We'll make the image fill the entire mark, leaving space for the border RelativeContainer = new PadesVisualRectangle() { Left = 0.1, Right = 0.1, Top = 0.1, Bottom = 0.1 }, // We'll use the 'Content/PdfStamp.png' as background. Image = new PdfMarkImage(Util.GetPdfStampContent(), "image/png") { // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque). Opacity = 50, } }); return(mark); case 3: // Example #3: 'Signed with RestPKI' is printed at the top of every page in a blue horizontal bar. // First, we create the mark object. It contains no elements, being a simple empty box. mark = new PdfMark() { // Then, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying left and right (but no width) results in a variable-width container with the given margins Left = 0, Right = 0, // Specifying top and height (but no bottom) results in a top-aligned fixed-height container Top = 0.5, Height = 1 }, // We'll not need a border, just a background color. BackgroundColor = Color.FromArgb(127, 0, 128, 192) }; // Add a single text element. mark.Elements.Add(new PdfMarkTextElement() { // We center the text. RelativeContainer = new PadesVisualRectangle() { // Specifying just the width results in a horizontally centered fixed-width container Width = 5, // Specifying just the height results in a vertically centered fixed-height container Height = 1 }, // Then add the text sections. TextSections = { // This example has a single section. new PdfTextSection() { // We set the text. Text = "Signed with RestPKI", // Its color. Color = Color.White, // Its size. FontSize = 12, // And the style. Style = PdfTextStyle.Bold } } }); return(mark); default: return(null); } }
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); }
// This function is called by the Pades Signature Starter action (see PadesSignatureController.cs). // It contains examples of PDF marks, isual elements of arbitrary content placed in every page. public static PdfMark GetPdfMark(int sampleNumber) { switch (sampleNumber) { case 1: // Example #1: A sample text and image are placed at the bottom of every page. // First, we create the mark object. It contains no elements, being a simple empty box. var mark = new PdfMark() { // Here, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying the width (but no left nor right) results in a horizontally centered fixed-width container Width = 8, // Specifying bottom and height (but no top) results in a bottom-aligned fixed-height container Bottom = 0.2, Height = 0.6 } // This example has no background and no borders, so we don't set BackgroundColor nor BorderColor }; // First, the image. mark.Elements.Add(new PdfMarkImageElement() { // We'll position it to the right of the text. RelativeContainer = new PadesVisualRectangle() { // Specifying right and width (but no left) results in a right-aligned fixed-width container Right = 0, Width = 1, // Specifying top and bottom (but no height) results in a variable-height container with the given margins Top = 0, Bottom = 0 }, // We'll use the image at 'Content/PdfStamp.png'. Image = new PdfMarkImage(Util.GetPdfStampContent(), "image/png") { // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque). Opacity = 75, } }); // Then, the text. mark.Elements.Add(new PdfMarkTextElement() { // We center the text. RelativeContainer = new PadesVisualRectangle() { // Specifying left and right (but no width) results in a variable-width container with the given margins Left = 1, Right = 0, // Specifying just the height results in a vertically centered fixed-height container Height = 0.5 }, // Then add the text sections. TextSections = { // First, a simple message. new PdfTextSection() { // We set the text. Text = "This document was digitally signed with ", // Its color. Color = Color.Black, // Its size. FontSize = 8, // And the style. Style = PdfTextStyle.Normal }, // And a bold ending. new PdfTextSection() { // We set the text. Text = "RestPKI", // Its color. Color = Color.Black, // Its size. FontSize = 8, // And the style. Style = PdfTextStyle.Bold } } }); return mark; case 2: // Example #2: An image will be placed at the bottom of every page. // First, we create the mark object. It contains no elements, being a simple empty box. mark = new PdfMark() { // Then, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying right and width (but no left) results in a right-aligned fixed-width container Right = 1, Width = 2.54, // Specifying bottom and height (but no top) results in a bottom-aligned fixed-height container Bottom = 1, Height = 2.54 }, // After that, its border must be configured. BorderWidth = 0.02, BorderColor = Color.Black }; // Add a single image element mark.Elements.Add(new PdfMarkImageElement() { // We'll make the image fill the entire mark, leaving space for the border RelativeContainer = new PadesVisualRectangle() { Left = 0.1, Right = 0.1, Top = 0.1, Bottom = 0.1 }, // We'll use the 'Content/PdfStamp.png' as background. Image = new PdfMarkImage(Util.GetPdfStampContent(), "image/png") { // Opacity is an integer from 0 to 100 (0 is completely transparent, 100 is completely opaque). Opacity = 50, } }); return mark; case 3: // Example #3: 'Signed with RestPKI' is printed at the top of every page in a blue horizontal bar. // First, we create the mark object. It contains no elements, being a simple empty box. mark = new PdfMark() { // Then, we set the mark's position in every page. Container = new PadesVisualRectangle() { // Specifying left and right (but no width) results in a variable-width container with the given margins Left = 0, Right = 0, // Specifying top and height (but no bottom) results in a top-aligned fixed-height container Top = 0.5, Height = 1 }, // We'll not need a border, just a background color. BackgroundColor = Color.FromArgb(127, 0, 128, 192) }; // Add a single text element. mark.Elements.Add(new PdfMarkTextElement() { // We center the text. RelativeContainer = new PadesVisualRectangle() { // Specifying just the width results in a horizontally centered fixed-width container Width = 5, // Specifying just the height results in a vertically centered fixed-height container Height = 1 }, // Then add the text sections. TextSections = { // This example has a single section. new PdfTextSection() { // We set the text. Text = "Signed with RestPKI", // Its color. Color = Color.White, // Its size. FontSize = 12, // And the style. Style = PdfTextStyle.Bold } } }); return mark; default: return null; } }
protected void Page_Load(object sender, EventArgs e) { var cadesSignatureContent = Storage.GetSampleCadesSignatureOfPdf(); var cadesSignature = Lacuna.Pki.Cades.CadesSignature.Open(cadesSignatureContent); var fontSize = 10; var markTexts = new List <PdfTextSection>() { new PdfTextSection() { Text = "Document digitally signed by ", FontSize = fontSize } }; for (int i = 0; i < cadesSignature.Signers.Count; i++) { var signer = cadesSignature.Signers[i]; if (i > 0) { markTexts.Add(new PdfTextSection() { Text = i < cadesSignature.Signers.Count - 1 ? ", " : " and ", FontSize = fontSize }); } markTexts.Add(new PdfTextSection() { Text = getDisplayName(signer.SigningCertificate), FontSize = fontSize, Style = PdfTextStyle.Bold }); } var mark = new PdfMark() { MeasurementUnits = Lacuna.Pki.Pades.PadesMeasurementUnits.Centimeters, Container = new Lacuna.Pki.Pades.PadesVisualRectangle() { Right = 1, Top = 1, Bottom = 1, Width = 2 }, BorderColor = Color.Black, BorderWidth = 0.01, BackgroundColor = Color.FromArgb(77, Color.LightGreen), // Light green with 30% opacity Elements = new List <PdfMarkElement>() { new PdfMarkText() { Rotation = PdfMarkRotation.D90, Texts = markTexts, RelativeContainer = new Lacuna.Pki.Pades.PadesVisualRectangle() { Left = 0.3, Top = 0.3, Bottom = 0.3, Right = 0.3 } } } }; var pdfMarker = new PdfMarker(); pdfMarker.AddMark(mark); var pdfWithMarks = pdfMarker.WriteMarks(cadesSignature.GetEncapsulatedContent()); Response.ContentType = "application/pdf"; Response.AddHeader("Content-Disposition", "attachment; filename=printable-version.pdf"); Response.BinaryWrite(pdfWithMarks); Response.End(); }