The following question and answer on StackOverflow show how to generate a PDF that cannot be opened without the appropriate password.
Password protected PDF using C#
I would like to use this framework similarly, but slightly altered to allow my users to "open" the PDF without needing the password, but only allow them to EDIT the PDF if they have the password.
Is that possible with iTextSharp?
if this matters, I am working in C# 4.0 within a WF 4.0 custom activity.
Another implementation:
public static void Common_PassWordProtectPDF_Static_WithoutEmail(FileInfo[] filteredfiles, string strAgentName, string strAgentCode, string strpassword, string strEmailID, string sourcefolder, string strdestfolder, string strdestinationFileName)
{
foreach (FileInfo file in filteredfiles)
{
//string sourcePdf = Convert.ToString(ConfigurationManager.AppSettings["SourceFolder"]) + "\\" + file.Name;
//string strdestPdf = Convert.ToString(ConfigurationManager.AppSettings["DestinationFolder"]) + file.Name;
string sourcePdf = sourcefolder + "\\" + file.Name;
string strdestPdf = strdestfolder + strdestinationFileName;
using (Stream input = new FileStream(sourcePdf, FileMode.Open, FileAccess.Read, FileShare.Read))
{
//sourcePdf unsecured PDF file
//destPdf secured PDF file
using (Stream output = new FileStream(strdestPdf, FileMode.Create, FileAccess.Write, FileShare.None))
{
PdfReader pdfReader = new PdfReader(input);
X509Store store = new X509Store("My");
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = new X509Certificate2();
RSACryptoServiceProvider csp = null;
AcroFields fields = pdfReader.AcroFields;
foreach (X509Certificate2 mCert in store.Certificates)
{
//TODO's
string strresult = mCert.GetName();
bool str123 = false;
if (strresult.Contains("Certificate name") == true)
{
csp = (RSACryptoServiceProvider)mCert.PrivateKey;
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(file.Name);
byte[] hash = sha1.ComputeHash(data);
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
if (Verify(file.Name, signature, mCert))
{
char s = pdfReader.PdfVersion;
//var pdfStamper = PdfStamper.(pdfReader, output, s, @"\0", true);
//csp.SignData(signature, true);
pdfReader.Appendable = false;
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
cp.ReadCertificate(mCert.RawData)};
IExternalSignature externalSignature = new X509Certificate2Signature(mCert, "SHA-1");
// var signedPdf = new FileStream(output, FileMode.Create);
// var signedPdf = PdfEncryptor.Encrypt(pdfReader, output, true, strpassword, strpassword, PdfWriter.ALLOW_PRINTING);
//char s = pdfReader.PdfVersion;
var pdfStamper = PdfStamper.CreateSignature(pdfReader, output, s, @"\", false);
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
byte[] USER = Encoding.ASCII.GetBytes("userpwd");
byte[] OWNER = Encoding.ASCII.GetBytes(strpassword);
Rectangle cropBox = pdfReader.GetCropBox(1);
float width = 108;
float height = 32;
// signatureAppearance.SignatureGraphic = Image.GetInstance("C:\\logo.png");
//signatureAppearance.Layer4Text = "document certified by";
//signatureAppearance.Reason = "Because I can";
//signatureAppearance.Location = "My location";
//signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 250, 150), pdfReader.NumberOfPages, "Signature");
Rectangle rect = new Rectangle(600, 100, 300, 150);
Chunk c = new Chunk("A chunk represents an isolated string. ");
rect.Chunks.Add(c);
//signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 600, 150), pdfReader.NumberOfPages, "Signature");
signatureAppearance.SetVisibleSignature(rect, pdfReader.NumberOfPages, "Signature");
// signatureAppearance.SetVisibleSignature(new Rectangle(cropBox.GetLeft(0), cropBox.GetBottom(0), cropBox.GetLeft(width), cropBox.GetLeft(height)), pdfReader.NumberOfPages, "Signature");
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
pdfStamper.SetEncryption(USER, OWNER, PdfWriter.AllowPrinting, PdfWriter.ENCRYPTION_AES_128);
MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
pdfStamper.Close();
// PdfEncryptor.Encrypt(pdfReader, output, true, strpassword, strpassword, PdfWriter.SIGNATURE_EXISTS);
}
else
{
Console.WriteLine("ERROR: Signature not valid!");
}
}
}
string Password = strpassword;
}
}
}
public static byte[] Sign(string text, string certSubject)
{
// Access Personal (MY) certificate store of current user
X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
my.Open(OpenFlags.ReadOnly);
// Find the certificate we’ll use to sign
RSACryptoServiceProvider csp = null;
foreach (X509Certificate2 cert in my.Certificates)
{
if (cert.Subject.Contains(certSubject))
{
// We found it.
// Get its associated CSP and private key
csp = (RSACryptoServiceProvider)cert.PrivateKey;
}
}
if (csp == null)
{
throw new Exception("No valid cert was found");
}
// Hash the data
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
// Sign the hash
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
}
static bool Verify(string text, byte[] signature, X509Certificate2 cert)
{
// Load the certificate we’ll use to verify the signature from a file
// X509Certificate2 cert = new X509Certificate2(certPath);
// Note:
// If we want to use the client cert in an ASP.NET app, we may use something like this instead:
// X509Certificate2 cert = new X509Certificate2(Request.ClientCertificate.Certificate);
// Get its associated CSP and public key
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key;
// Hash the data
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
// Verify the signature with the hash
return csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature);
}
Yes, there are two passwords that you can pass to PdfEncryptor.Encrypt()
, userPassword
and ownerPassword
. Just pass null
to the userPassword
and people will be able to open it without specify a password.
string WorkingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string InputFile = Path.Combine(WorkingFolder, "Test.pdf");
string OutputFile = Path.Combine(WorkingFolder, "Test_enc.pdf");
using (Stream input = new FileStream(InputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (Stream output = new FileStream(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
PdfReader reader = new PdfReader(input);
PdfEncryptor.Encrypt(reader, output, true, null, "secret", PdfWriter.ALLOW_SCREENREADERS);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With