准備條件:
1. 需要一個pfx的証書文件
怎麼樣產生這個PDF的証書文件呢?
a、 从CA获得
如果是商业应用最好从证书的签发机构CA获得证书,比如VeriSign,这样的大的CA签发的证书已经被一些系统默认为可信任的证书签发机构,它所签发的证书也是被信任的。但是这样的证书需要购买。
如果不是商业应用,这里推荐一个可以免费申请证书的CA:www.cacert.org
b、 从windows2003证书服务中获得
在windows2003中安装证书服务器,windows2003服务器即可当做一个小型的CA,可以申请签发证书。
c、 使用makecert工具获得 (仅用于测试目的的 X.509 证书)
微软在framework SDK中提供了一个生成X.509数字证书的命令行工具Makecert.exe。
Makecert生成证书被保存到命令中指定的证书存储区。
比如使用下面这个命令生成一个证书:
makecert -r -pe -n "CN=PLMM" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my
参数说明:
-sr CurrentUser //指定主题的证书存储位置。Location 可以是 currentuser(默认值)或 localmachine-ss My //指定主题的证书存储名称,输出证书即存储在那里。My表示保存在“个人”-n CN=MyTestCert //指定主题的证书名称。此名称必须符合 X.500 标准。最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,"CN=myName"。-sky exchange //指定颁发者的密钥类型,必须是 signature、exchange 或一个表示提供程序类型的整数。默认情况下,可传入 1 表示交换密钥,传入 2 表示签名密钥。-pe //将所生成的私钥标记为可导出。这样可将私钥包括在证书中。
这个命令生成一个名字为MyTestCert的证书,被保存到了当前用户的个人证书存储区内。
Makecert命令的详细说明请参看微软Makecert.exe工具的文档:http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cptools/html/cpgrfcertificatecreationtoolmakecertexe.asp
這個時候你就可以在IE工具欄菜單 工具>選項>內容>憑証>個人 下看到一個PLMM的憑証,這個時候你可以把這個憑証導出來產生一個PFX文件即可.
正式的時候請到官方去申請PFX文件......
2. 需要引用itextsharp.dll文件
a. 所使用到iTextsharp中的對象及方法說明:
PKCS12Store : 証書文件(這里對應的是pfx的証書文件)
PdfStamper : PDF文件對象(這里就當成一個PDF文件吧)
PdfSignatureAppearance : 給PDF簽名的對象
PdfSignatureAppearance.SetCrypto : 將証書文件邦定到PDF檔
PdfSignatureAppearance.Reason : 設置數字簽名的理由
PdfSignatureAppearance.Contact : 設置數字簽名的簽署者聯絡資訊
PdfSignatureAppearance.Location : 設置數字簽名的位置
b. 產生步驟:
1. 將要加入數字簽名的PDF文件讀入iTextsharp的PdfReader對象中
2. 利用這個PdfReader對象來產生一個新的PDF對象PdfStamper
3. 取得這個新的PDF對象的數字簽名對象:PdfSignatureAppearance
4. 取得一個數字証書文件文件對象(這里取得的是pfx數字簽名文件)
5. 將這個數字証書文件加入到新PDF對象中
6. 設計新PDF文件數字証書的屬性:數字簽名的理由、數字簽名的簽署者聯絡資訊、數字簽名的位置
7. 另存為這個新的PDF文件
8. 數字証書文件文件對象的取得:實例化一個PKCS12Store對象,參數為這個pfx文件的路徑及密碼
asp.net代碼給PDF加入數字簽名:
// pfx憑証類
public class Cert
{
private string path = "";
private string password = "";
private AsymmetricKeyParameter akp;
private org.bouncycastle.x509.X509Certificate[] chain;
public org.bouncycastle.x509.X509Certificate[] Chain
{
get { return chain; }
}
public AsymmetricKeyParameter Akp
{
get { return akp; }
}
public string Path
{
get { return path; }
}
public string Password
{
get { return password; }
set { password = value; }
}
public Cert() { }
public Cert(string cpath)
{
this.path = cpath;
this.processCert();
}
public Cert(string cpath, string cpassword)
{
this.path = cpath;
this.Password = cpassword;
this.processCert();
}
private void processCert()
{
string alias = null;
PKCS12Store pk12;
//取得証書文件
pk12 = new PKCS12Store(new FileStream(this.Path, FileMode.Open, FileAccess.Read), this.password.ToCharArray());
IEnumerator i = pk12.aliases();
while (i.MoveNext())
{
alias = ((string)i.Current);
if (pk12.isKeyEntry(alias))
break;
}
this.akp = pk12.getKey(alias).getKey();
X509CertificateEntry[] ce = pk12.getCertificateChain(alias);
this.chain = new org.bouncycastle.x509.X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
chain[k] = ce[k].getCertificate();
}
}
// 給源PDF文件加上數字簽名後產生一個新的PDF文件
public void PDFSigner(string inputFile, string outputFile, Cert myCert, string sigReason, string sigContact, string sigLocation)
{
PdfReader reader = new PdfReader(inputFile);
PdfStamper st = PdfStamper.CreateSignature(reader, new FileStream(outputFile, FileMode.Create, FileAccess.Write), '\0', null, true);
PdfSignatureAppearance sap = st.SignatureAppearance;
//設置PDF的數字簽名
sap.SetCrypto(myCert.Akp, myCert.Chain, null, PdfSignatureAppearance.WINCER_SIGNED);
//設置數字簽名的理由
sap.Reason = sigReason;
//設置數字簽名的簽署者聯絡資訊
sap.Contact = sigContact;
//設置數字簽名的位置
sap.Location = sigLocation;
//設置是否在PDF頁面中顯示數字簽名的圖標
sap.SetVisibleSignature(new iTextSharp.text.Rectangle(100, 100, 250, 150), 1, null);
st.Close();
reader.Close();
}