Related
I need to sign pdf with external web service. But there is an error on signed pdf like Document has been altered or corrupted since it was signed.
static void Main(string[] args)
{
//StreamSign();
PdfReader reader = new PdfReader(#"E:\pdf-exampleSign\example.pdf");
//MemoryStream os = new MemoryStream();
FileStream os = File.OpenWrite(#"E:\pdf-exampleSign\example_tmp.pdf");
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, "Signature");
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, 20000);
byte[] hash = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());
StringBuilder builder = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
builder.Append(hash[i].ToString("x2"));
}
var hex = builder.ToString();
//HERE IS THE SERVER SIDE BASE64 STRING I GOT
string ServerSideSignedBytes = "MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgE.....";
byte[] signbytes = Convert.FromBase64String(ServerSideSignedBytes);
X509Certificate2 certt = new X509Certificate2(signbytes);
var cert = new Org.BouncyCastle.X509.X509CertificateParser().ReadCertificate(certt.GetRawCertData());
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[1];
chain[0] = cert;
using (PdfReader prereader = new PdfReader(#"E:\pdf-exampleSign\example_tmp.pdf"))
{
using (FileStream preos = File.OpenWrite(#"E:\pdf-exampleSign\example_signed.pdf"))
{
IExternalSignatureContainer externallast = new MyExternalSignatureContainer(signbytes, chain);
MakeSignature.SignDeferred(prereader, "Signature", preos, externallast);
}
}
}
public class MyExternalSignatureContainer : IExternalSignatureContainer
{
protected byte[] sig;
protected Org.BouncyCastle.X509.X509Certificate[] chain;
public MyExternalSignatureContainer(byte[] sig, Org.BouncyCastle.X509.X509Certificate[] chain)
{
this.sig = sig;
this.chain = chain;
}
public byte[] Sign(Stream s)
{
return sig;
}
public void ModifySigningDictionary(PdfDictionary signDic) { }
}
I do apply a signature to a pdf document via delayed signing(SignDeferred) using IText.
The process contains the following steps:
Prepare the pdf document for siging
Reserve space for the signature in the pdf document
Create the hash value of the pdf document
Create the signature based on the hash value
Using a self signed certificate
Apply the signature to the pdf document
The whole process works and i end with a pdf document where the signature is set and is valid.
The original pdf is a PDF-A1a but the resulting pdf is not a valid PDF-A1a anymore.
I am aware that there is a documentation about IText PDF-A support (https://kb.itextpdf.com/home/it7kb/ebooks/itext-7-jump-start-tutorial-for-java/chapter-7-creating-pdf-ua-and-pdf-a-documents), but this seems to not apply since i don't change the content of the document.
My question:
How can i apply a signature using deferred signing and keep the PDF-A1a in the resulting document?
Note: If i do apply a signature directly (Without SignDeferred), the resulting pdf is still a PDF-A1a, but i do have to use SignDeferred
Note: I do use https://www.pdfen.com/pdf-a-validator for checking pdf-A
Code sample
Component used for signing:
itext.sign 7.1.5.0
itext.kernel 7.1.5.0
Component used for creating hash
BouncyCastle.Crypto 1.8.1.0
The following is a complete code sample sample with everything required in one file.
It only requires the references to itext and BouncyCastle and the path to a self signed certificate
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
namespace DeferredSigningTestConsole
{
class Program
{
static string SignatureAttributeName = "DeferredSignature";
static string CertificatePath = #"C:\temp\PDFA\PdfATestCert.2pfx.pfx";
static string CertificatePassword = "test";
static void Main(string[] args)
{
var signedPdf = SignPdf(System.IO.File.ReadAllBytes(#"C:\temp\PDFA\PDF_A1a.pdf"));
System.IO.File.WriteAllBytes(#"C:\temp\PDFA\signed.pdf", signedPdf);
}
public static byte[] SignPdf(byte[] pdfToSign)
{
byte[] hash = null;
byte[] tmpPdf = null;
//Step #1 >> prepare pdf for signing (Allocate space for the signature and calculate hash)
using (MemoryStream input = new MemoryStream(pdfToSign))
{
using (var reader = new PdfReader(input))
{
StampingProperties sp = new StampingProperties();
sp.UseAppendMode();
using (MemoryStream baos = new MemoryStream())
{
var signer = new PdfSigner(reader, baos, sp);
signer.SetCertificationLevel(PdfSigner.NOT_CERTIFIED);
signer.SetFieldName(SignatureAttributeName);
DigestCalcBlankSigner external = new DigestCalcBlankSigner(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signer.SignExternalContainer(external, 121743);
hash = external.GetDocBytesHash();
tmpPdf = baos.ToArray();
}
}
//Step #2 >> Create the signature based on the document hash
byte[] signature = GetSignatureFromHash(hash);
//Step #3 >> Apply the signature to the document
ReadySignatureSigner extSigContainer = new ReadySignatureSigner(signature);
using (MemoryStream preparedPdfStream = new MemoryStream(tmpPdf))
{
using (var pdfReader = new PdfReader(preparedPdfStream))
{
using (PdfDocument docToSign = new PdfDocument(pdfReader))
{
using (MemoryStream outStream = new MemoryStream())
{
PdfSigner.SignDeferred(docToSign, SignatureAttributeName, outStream, extSigContainer);
return outStream.ToArray();
}
}
}
}
}
}
public static byte[] GetSignatureFromHash(byte[] hash)
{
FileStream fs = new FileStream(CertificatePath, FileMode.Open);
Pkcs12Store store = new Pkcs12Store(fs, CertificatePassword.ToCharArray());
String alias = "";
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate)
{
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
X509CertificateEntry[] chain = store.GetCertificateChain(alias);
List<Org.BouncyCastle.X509.X509Certificate> c = new List<Org.BouncyCastle.X509.X509Certificate>();
foreach (X509CertificateEntry en in chain)
{
c.Add(en.Certificate);
}
PrivateKeySignature signature = new PrivateKeySignature(pk.Key, "SHA256");
String hashAlgorithm = signature.GetHashAlgorithm();
PdfPKCS7 sgn = new PdfPKCS7(null, c.ToArray(), hashAlgorithm, false);
DateTime signingTime = DateTime.Now;
byte[] sh = sgn.GetAuthenticatedAttributeBytes(hash, null, null, PdfSigner.CryptoStandard.CMS);
byte[] extSignature = signature.Sign(sh);
sgn.SetExternalDigest(extSignature, null, signature.GetEncryptionAlgorithm());
return sgn.GetEncodedPKCS7(hash, null, null, null, PdfSigner.CryptoStandard.CMS);
}
}
internal class DigestCalcBlankSigner : IExternalSignatureContainer
{
private readonly PdfName _filter;
private readonly PdfName _subFilter;
private byte[] _docBytesHash;
internal DigestCalcBlankSigner(PdfName filter, PdfName subFilter)
{
_filter = filter;
_subFilter = subFilter;
}
internal virtual byte[] GetDocBytesHash()
{
return _docBytesHash;
}
public virtual byte[] Sign(Stream docBytes)
{
_docBytesHash = CalcDocBytesHash(docBytes);
//If we retun the signature bytes, GetAuthenticatedAttributeBytes will throw an exception
//Not clear how this should be done
return new byte[0];
}
public virtual void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.Filter, _filter);
signDic.Put(PdfName.SubFilter, _subFilter);
}
internal static byte[] CalcDocBytesHash(Stream docBytes)
{
byte[] docBytesHash = null;
docBytesHash = DigestAlgorithms.Digest(docBytes, DigestUtilities.GetDigest(DigestAlgorithms.SHA256));
return docBytesHash;
}
}
internal class ReadySignatureSigner : IExternalSignatureContainer
{
private byte[] cmsSignatureContents;
internal ReadySignatureSigner(byte[] cmsSignatureContents)
{
this.cmsSignatureContents = cmsSignatureContents;
}
public virtual byte[] Sign(Stream docBytes)
{
return cmsSignatureContents;
}
public virtual void ModifySigningDictionary(PdfDictionary signDic)
{
}
}
}
It seems the reason why the signed pdf is no longer a valid PDF-A1a is the estimated size for the signature.
I have used a value of about 120kb for the signature.
//doesn't work
signer.SignExternalContainer(external, 121743);
//does work
signer.SignExternalContainer(external, 65000);
The concept of this is documented in the ebook "Digital Signatures for PDF documents" from iText.
It seems in order to get a valid pdf-A1a the maximum size is limited to 65kb.
I now will have to test whether this works when i add a visual representation (signature image) since this was the reason i did choose such a large estimated size.
Edit:
I did some more testing and i am now able to produce valid pdf-A document with signatures:
The pdf are now valid pdf-A with the changed estimated size:
Valid with estimate size 32'000/65'000
A1a
A1b
Valid with estimate size 32'000
A2a
A2b
A2u
A3a
A3b
A3u
When adding a visual representation (image), pdf-A1a and pdf-A1b are no longer valid.
A transparent soft mask is present. Beginning with PDF 1.4 transparency is supported. Some PDF-based ISO standards prohibit the use of transparency.
But this is another problem which i now try to figure out.
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.
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);
}
}
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);
}
From what I understood, if I want to sign the SAML request, the signature should be constructed of:
SAMLRequest=VALUE&RelayState=VALUE&SigAlg=VALUE
and from that I should create the signature, this is the piece of code I have used in order to create the signature:
var MSCert = new X509Certificate2(ConfigurationManager.AppSettings["KeyFilepath"], ConfigurationManager.AppSettings["KeyFilePassword"]);
RSACryptoServiceProvider rsacsp = (RSACryptoServiceProvider)MSCert.PrivateKey;
CspParameters cspParam = new CspParameters();
cspParam.KeyContainerName = rsacsp.CspKeyContainerInfo.KeyContainerName;
cspParam.KeyNumber = rsacsp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2;
RSACryptoServiceProvider aescsp = new RSACryptoServiceProvider(cspParam);
aescsp.PersistKeyInCsp = false;
byte[] signed = aescsp.SignData(requestBytes, "SHA256");
// For testing purposes - testing the signature
bool isValid = aescsp.VerifyData(requestBytes, "SHA256", signed);
string signatureValue = null;
// Deflate the signature string
using (var output = new MemoryStream())
{
using (var zip = new DeflateStream(output, CompressionMode.Compress))
{
zip.Write(signed, 0, signed.Length);
}
var base64 = Convert.ToBase64String(output.ToArray());
var urlEncode = HttpUtility.UrlEncode(base64);
signatureValue = urlEncode;
}
And still, I see that the validation fails, can some one help me to see why?
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.
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);
}
}
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);
}