PDF Merging With Digital Signature and Password Protection

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 7

pDF Merging with Digital Signature and

Password Protection
Gunaprasad Shetty, 7 Jun 2017

4.26 (10 votes)

1 2 3 4 5

4.26/5 - 10 votes
μ 4.00, σa 1.98 [?]

Rate this: Vote!


vote 1vote 2vote 3vote 4vote 5
Please Sign up or sign in to vote.
The tip will help you understand how the Word document can be converted into PDF and merge
it as single PDF with digital signature for the secured transport of PDF.

Introduction
The tip will help you understand how a Word document can be converted to PDF and merge it as
single PDF with a digital signature for the secured transport of PDF.

Background
This tip will give a basic idea to merge the PDFs into a single PDF from a Word doc, which can
then be digitally signed using AsymmetricKey values by using various DLLs in conjunction.

The tip demonstrates the following points:

 Replacing the word in the Word document and converting into PDF
 Merging the list of PDF into Single PDF using Spire.Pdf
 Digitally signing the PDF and placement of Signature in the PDF
 Password protection of the signed PDF document

Using the Code


The code example below uses various DLLs to accomplish the task.

1. This code provides the demonstration of how to merge the set of PDF documents into a single
PDF
2. Digitally sign the merged PDF document
3. Password protection of the digitally signed PDF document.
Below is the list of DLLs which are used, please include this essential DLL into the source code
before using the code.

Part 1 - Variable Declaration and Initialization


Hide Copy Code
using iTextSharp.text;
using iTextSharp.text.pdf;
using Microsoft.Office.Interop.Word;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using Spire.Pdf;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;

Pkcs12Store pk12;
//First we'll read the certificate file and declare the certificate variable,
//a pfx file will be used and a password will be provided to validate the pfx file.
try
{
pk12 = new Pkcs12Store(new FileStream(txtSignature.Text, FileMode.Open, FileAccess.Read),
txtPassword.Text.ToCharArray());
}
catch (Exception ex)
{
MessageBox.Show("Signature Passsword incorrect" + ex.Message);
return;
}

In the above piece of code:

1. We are declaring the certificate variables


2. Pkcs12Store Store is instantiated which takes four parameters:
1. Signature text provided by user
2. FileMode
3. Accesstype
4. Password provided by the user

These parameters would be used by the Pkcs12Store to access the certificate having a pfx
extension. This certificate will be used later for digitally signing the document in the below code.

Part 2 - Loading the Document and Replacing the Values from the
Database

Hide Shrink Copy Code


#region Firstpage Document to pdf conversion and replacing of values
object fileName = Path.GetFullPath
(ConfigurationManager.AppSettings["TemplateDocument"].ToString());
Word.Application wordApp = new Word.Application { Visible = false };
Word.Document aDoc =
wordApp.Documents.Open(ref fileName, ReadOnly: true, Visible: false);

aDoc.Activate();
string text = wordApp.ActiveDocument.Content.Text;
Word.Find fnd = wordApp.ActiveDocument.Content.Find;
fnd.ClearFormatting();
fnd.Replacement.ClearFormatting();
fnd.Forward = true;
fnd.Wrap = Word.WdFindWrap.wdFindContinue;
fnd.Text = "[##FormName]";
fnd.Replacement.Text = formName;
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##COMPANY]";
fnd.Replacement.Text =
((System.Data.DataRowView)(cmbEntity.SelectedItem)).Row.ItemArray[2].ToString();
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##NAME]";
fnd.Replacement.Text = Convert.ToString(dr[0]["RES_DESC"]);
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##EMP_CODE]";
fnd.Replacement.Text = Convert.ToString(row["Emp_Code"]);
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
// // Any source code blocks look like this //
fnd.Text = "[##EMP_PAN]";
if (!String.IsNullOrEmpty(Convert.ToString(row["PAN_Number"])))
fnd.Replacement.Text = Convert.ToString(row["PAN_Number"]);
else
fnd.Replacement.Text = "PANNOTAVBL";
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##EMP_DESG]";
fnd.Replacement.Text = Convert.ToString(dr[0]["RES_DESIGNATION"]);
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##FINANCIAL_YEAR]";
fnd.Replacement.Text = Convert.ToString(cmbYear.SelectedItem.ToString());
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);
fnd.Text = "[##ASSESMENT_YEAR]";

var assesmentperiod = CalculateAssesmentYear


(Convert.ToString(cmbYear.SelectedItem.ToString()),"AP");
fnd.Replacement.Text = assesmentperiod.Item1+" - "+assesmentperiod.Item2;
fnd.Execute(Replace: Word.WdReplace.wdReplaceAll);

The above code reads the Doc Template, replaces the values from the database and converts it
into the document that would be used by PDF conversion object.

Part 3 - Assigning User Name and Password to the Document for


Authentication and Converting from Document to PDF
The code below explains how the files are read from the directory and are assigned with the
security username and password before converting it to the secured or protected PDF files.

Hide Shrink Copy Code


object oMissing = System.Reflection.Missing.Value;
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetFullPath
(ConfigurationManager.AppSettings["TemplateDocument"].ToString()));
outputFileName = Path.GetFullPath(ConfigurationManager.AppSettings
["EmployeeFirstPage"].ToString()) +
Convert.ToString(row["Emp_Code"]) +
dirInfo.Name.Replace(".docx", ".pdf");
object fileFormat = Word.WdSaveFormat.wdFormatPDF;
// Save document into PDF Format
if (File.Exists(Convert.ToString(outputFileName)))
{
File.Delete(Convert.ToString(outputFileName));
}
aDoc.SaveAs(ref outputFileName,
ref fileFormat, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing);
object saveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
((_Document)aDoc).Close(ref saveChanges, ref oMissing, ref oMissing);
aDoc = null;
((_Application)wordApp).Quit(ref oMissing, ref oMissing, ref oMissing);
wordApp = null;
// DoSearchAndReplaceInWord();
#endregion First page document
#region merging of entire documents
//PdfDocument outputDocument = new PdfDocument();

List<string> lstfirspage = new List<string>();


lstfirspage.Add(outputFileName.ToString());
lstfirspage.AddRange(lstdocuments);
try
{
// Save the document...
PdfDocumentBase doc = Spire.Pdf.PdfDocument.MergeFiles(lstfirspage.ToArray<string>());
Spire.Pdf.Security.PdfSecurity securitySettings = doc.Security;
string year = Convert.ToString(cmbYear.SelectedItem);
string filename = Convert.ToString(row["Emp_Code"])+ "_Form16_" + year;
string outputUnSignedFile = @"" + txtDestination.Text +
"\\TUnSigned\\" + filename + ".pdf";

outputFile = @"" + txtDestination.Text + "\\" + filename + ".pdf";


if (!String.IsNullOrWhiteSpace(Convert.ToString(row["PAN_Number"])))
{
if ((Convert.ToString(dr[0]["Res_Status"]) == "Active"))
{
securitySettings.UserPassword = Convert.ToString(row["PAN_Number"]).ToUpper();
securitySettings.OwnerPassword = Convert.ToString(row["PAN_Number"]).ToUpper();
}
word = "PAN in uppercase";
if (File.Exists(txtSource.Text + "\\" + TraceFile + ".pdf"))
{
if (File.Exists(outputUnSignedFile))
{
File.Delete(outputUnSignedFile);
}
doc.Save(outputUnSignedFile, FileFormat.PDF);
}
else
{
if (File.Exists(outputFile))
{
File.Delete(outputFile);
}
doc.Save(outputFile, FileFormat.PDF);
}
}
else
{
if ((Convert.ToString(dr[0]["Res_Status"]) == "Active"))
{
securitySettings.UserPassword = Convert.ToString(row["Emp_Code"]).ToUpper();
securitySettings.OwnerPassword = Convert.ToString(row["Emp_Code"]).ToUpper();
}
word = "Employee Code";
if (File.Exists(outputFile))
{
File.Delete(outputFile);
}
doc.Save(outputFile, FileFormat.PDF);
}
doc.Close();
Spire.Pdf.PdfDocument finaldoc = new Spire.Pdf.PdfDocument();
if (File.Exists(txtSource.Text + "\\" + TraceFile + ".pdf")
&& !String.IsNullOrWhiteSpace(Convert.ToString(row["PAN_Number"])))
{
if (File.Exists(outputFile))
{
File.Delete(outputFile);
}

Part 4 - Digitally Signing the PDF Document using SpirePdf and


Asymmetric Key
The following code iterates through the private key entry and finds the suitable one, once the
certificate is found the unsigned file will be verified for the signed certificate or key. Once the
appropriate key is found, the output will show the green tick mark which satisfies that the PDF
has been digitally verified through the desired or the provided certificate.

Hide Shrink Copy Code


string alias = null;
//then Iterate through certificate entries to find the private key entry
System.Collections.IEnumerator i = pk12.Aliases.GetEnumerator();
while (i.MoveNext())
{
alias = ((string)i.Current);
if (pk12.IsKeyEntry(alias))
break;
}
AsymmetricKeyParameter Akp = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
chain[k] = ce[k].Certificate;

char[] chararr = Convert.ToString(row["PAN_Number"]).ToUpper().ToCharArray();


Byte[] b = new Byte[chararr.Length];
for (int ifor = 0; ifor < chararr.Length; ifor++)
b[ifor] = Convert.ToByte(chararr[ifor]);
PdfReader reader = new PdfReader(outputUnSignedFile,b);
FileStream fout = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
PdfStamper stp = PdfStamper.CreateSignature(reader, fout, '\0');
if ((Convert.ToString(dr[0]["Res_Status"]) == "Active"))
{
stp.SetEncryption(true, Convert.ToString(row["PAN_Number"]).ToUpper(),
Convert.ToString(row["PAN_Number"]).ToUpper(),
PdfWriter.ALLOW_SCREENREADERS | PdfWriter.ALLOW_PRINTING);
}
PdfSignatureAppearance sap = stp.SignatureAppearance;
sap.SetCrypto(Akp, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
sap.CertificationLevel = PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED;
Spire.Pdf.PdfDocument doccount = new Spire.Pdf.PdfDocument();
doccount.LoadFromFile(txtSource.Text + "\\" + TraceFile + ".pdf");
sap.SetVisibleSignature(new iTextSharp.text.Rectangle(545,40,455,80),
doccount.Pages.Count + 1, "Signature");
stp.Close();
}
try
{
if (File.Exists(outputUnSignedFile))
{
File.Delete(outputUnSignedFile);
}
if (File.Exists(Convert.ToString(outputFileName)))
{
File.Delete(Convert.ToString(outputFileName));
}
}
catch (Exception)
{

}
finally
{

}
#endregion merging of documents
}

The above code provides a small example of digitally signing and merging PDFs. Developers can
use them accordingly for their use with modification according to the requirement.

Thanks for reading! Vote if you find it helpful!

&amp;amp;amp;amp;lt;a
href="https://pubads.g.doubleclick.net/gampad/jump?iu=/6839/lqm.codeproject.site/Web-
Development/ASP-
NET/Howto&amp;amp;amp;amp;amp;sz=300x250&amp;amp;amp;amp;amp;c=480156"&amp;am
p;amp;amp;gt;&amp;amp;amp;amp;lt;img
src="https://pubads.g.doubleclick.net/gampad/jump?iu=/6839/lqm.codeproject.site/Web-
Development/ASP-
NET/Howto&amp;amp;amp;amp;amp;sz=300x250&amp;amp;amp;amp;amp;c=480156"
width="300px" height="250px"
target="_blank"/&amp;amp;amp;amp;gt;&amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;gt;

Don't like this Ad?


1. Hit the refresh icon to show the ad again so you can take a screenshot
2. Drag and Drop or paste the screenshot here
Offensive

License
This article, along with any associated source code and files, is licensed under The Code Project
Open License (CPOL)

Share

You might also like