摘 要 在Internet網絡走進千家萬戶的今天。網上在線申請業務變得越來越普遍。本系統采用數字簽名技術,在保障用戶申請文件及網絡上傳過程中安全性的同時,保障了傳輸文件的完整性及真偽的可驗證性。
關鍵詞 網絡安全,數字簽名, SHA1WithDSA,公鑰加密技術
一、引言
隨著Internet的飛速發展,網上業務申請變得越來越普及,經常會出現雙方在不見面的情況下,通過申請文件的提交,達到業務申請的目的。由于Internet網絡的一些不安全因素,提交的申請文件可能在網上傳輸的過程中,被劫取、篡改、偽造或發生發送方抵賴等問題。那么如何保證申請文件的真實性、在網絡傳輸中的完整性及申請人的不可抵賴性就成了安全地完成網絡業務申請的關鍵。
簽名是證明當事者的身份和數據真實性的一種信息,可以用不同的形式來表示。一種完善的簽名應滿足以下三個條件:簽名者事后不能抵賴自己的簽名;任何其他人不能偽造簽名;如果當事人雙方關于簽名的真偽發生爭執,能夠在公正的仲裁者面前通過驗證來確認其真偽。
在傳統的書面文件為基礎的事務處理中,手簽、印章、手印等書面簽名基本上滿足以上條件,因而得到司法部門的支持,具有一定的法律意義。
在以計算機文件為基礎的現代事務處理中,采用電子形式的簽名。目前的數字簽名是建立在公開密鑰體制基礎上,它是公開密鑰加密技術的另一類應用。它的主要方式是:報文的發送方從報文文本中生成一個128位的散列值(或報文摘要);發送方用自己的私人密鑰對這個散列值進行加密來形成發送方的數字簽名。然后,這個數字簽名將作為報文的附件和報文一起發送給報文的接收方;報文的接收方首先從接收到的原始報文中計算出128位的散列值(或報文摘要),接著再用發送方的公用密鑰來對報文附加的數字簽名進行解密。如果兩個散列值相同、那么接收方就能確認該數字簽名是發送方的。
通過數字簽名能夠實現對原始報文的鑒別,我國1995年制定了自己的數字簽名標準(GB15851-1995),使其具有法律意義,由于數字簽名利用密鑰技術進行,因而可以獲得比書面簽名更高的安全性。
公開密鑰加密技術的體制是,申請人具有一對密鑰,一個是私鑰,自行保存,用于文件的數字簽名;一個是公鑰,公開發布,用于接收方驗證簽名。由于私鑰只有申請人自己持有,而且只有用申請人的私鑰加密的文件,才能用申請人的公鑰進行解密驗證,所以在保障信息安全的同時,保障了申請人的不可抵賴性。
本文的數字簽名方式采用的是公開密鑰算法DSA和報文摘要算法SHA-1的融合。
二、系統的設計
本系統分為客戶端和服務器端,客戶端軟件采用Java技術生成用戶所需密鑰對,并產生簽名文件;服務端采用JSP技術實現客戶申請文件的上傳,接受方則利用客戶端軟件進行申請文件的簽名驗證。
1.客戶端
(1) 密鑰對的生成方法keyPair()
1) 相關介紹
KeyPairGenerator 類:用于生成公鑰和私鑰對。密鑰對生成器是使用 getInstance 工廠方法(返回一個給定類的實例的靜態方法)構造的。 特定算法的密鑰對生成器創建可與此算法一起使用的公鑰/私鑰對,也將每個生成的密鑰與特定于算法的參數相關聯。每個提供程序都必須提供(并記錄)默認的初始化,以防客戶沒有顯式初始化 KeyPairGenerator(通過調用 initialize 方法)。例如,Sun 提供程序使用 1024 位的默認模大。荑大。。
2) 核心源碼
KeyPairGenerator keyGen=KeyPairGenerator.getInstance("DSA");//使用DSA算法
keyGen.initialize(1024,new SecureRandom());
KeyPair pair=keyGen.generateKeyPair();
PublicKey pub=pair.getPublic();
PrivateKey priv=pair.getPrivate();
pubkey=pub.getEncoded();
privKey= priv.getEncoded();
fileOut=new FileOutputStream("sigPublicKey.dat");//輸出簽名公鑰文件
fileOut.write(pubkey);
fileOut.close();
fileOut=new FileOutputStream("sigPrivateKey.dat");//輸出簽名私鑰文件
fileOut.write(privKey);
fileOut.close();
(2) 數字簽名方法signFile()
1) 相關介紹
KeyFactory 類:密鑰工廠是用來將 keys(Key 類型的不透明加密密鑰)轉換成 key 規范(基礎密鑰材料的透明表示),反之亦然。 密鑰工廠是雙向的。也就是說,它們允許根據一個給定的密鑰規范(密鑰材料)來建造一個不透明的密鑰對象,也可以檢索以合適格式表示的密鑰對象的基礎密鑰材料。
2) 核心源碼
fileIn2=new FileInputStream(jTextField2.getText()); //獲取私鑰文件
byte[] encodedprivKey=new byte[fileIn2.available()];
fileIn2.read(encodedprivKey);
fileIn2.close();
PKCS8EncodedKeySpec privKeySpec= new PKCS8EncodedKeySpec(encodedprivKey);
KeyFactory keyFactory=KeyFactory.getInstance("DSA");
PrivateKey privKey=keyFactory.generatePrivate(privKeySpec);
Signature dsa=Signature.getInstance("SHA1WithDSA"); //簽名采用DSA和SHA1融合算法
dsa.initSign(privKey);
FileInputStream fis=new FileInputStream(jTextField1.getText()); //獲取原文件
while(fis.available()!=0){
temp=(byte)fis.read();
dsa.update(temp);
}
fis.close();
byte[] sig=dsa.sign();
fileOut1=new FileOutputStream(jTextField3.getText()); //輸出簽名文件
fileOut1.write(sig);
fileOut1.close();
JOptionPane.showMessageDialog(null, "簽名文件生成成功 "+jTextField3.getText(),"確認消息", JOptionPane.INFORMATION_MESSAGE);
(3) 簽名驗證方法verifyFile()
1) 相關介紹
Signature 類:用來為應用程序提供數字簽名算法功能。其方法public final byte[] sign() throws SignatureException返回所有已更新數據的簽名字節,簽名的格式取決于基礎簽名方案;方法public final boolean verify(byte[] signature) throws SignatureException,驗證傳入的簽名。
2) 核心源碼
fileIn3=new FileInputStream(jTextField5.getText()); //獲取公鑰文件
byte[] encodedpubKey =new byte[fileIn3.available()];
fileIn3.read(encodedpubKey);
fileIn3.close();
X509EncodedKeySpec pubKeySpec= new X509EncodedKeySpec(encodedpubKey);
KeyFactory keyFactory=KeyFactory.getInstance("DSA");
PublicKey pubKey=keyFactory.generatePublic(pubKeySpec);
FileInputStream sigStream=new FileInputStream(jTextField6.getText()); //獲取簽名文件
byte[] signature=new byte[sigStream.available()];
sigStream.read(signature);
sigStream.close();
Signature sigObj=Signature.getInstance("SHA1WithDSA");
sigObj.initVerify(pubKey);
fileIn4=new FileInputStream(jTextField4.getText());
byte temp;
while((fileIn4.available())!=0)
{
temp=(byte)fileIn4.read();
sigObj.update(temp);
};
fileIn4.close();
boolean verifies;
if( verifies=sigObj.verify(signature))
JOptionPane.showMessageDialog(null, jTextField4.getText()+" 文件驗證通過","確認消息", JOptionPane.INFORMATION_MESSAGE);
else
JOptionPane.showMessageDialog(null, jTextField4.getText()+" 文件驗證失敗","確認消息", JOptionPane.INFORMATION_MESSAGE);
}
2.服務器
本程序這部分主要為了程序演示,采用JSP技術實現了文件上傳功能。為了實現穩定的上傳功能,程序使用第三方的類庫cos。文件fileload.jsp主要代碼如下:
// 上傳文件
MultipartRequest multi = new MultipartRequest(request, saveDirectory, maxPostSize,"GBK" );
<%
// 取得所有上傳文件名稱
Enumeration filesname = multi.getFileNames();
while (filesname.hasMoreElements())
{
String name = (String) filesname.nextElement();
fileName = multi.getFilesystemName(name);
File f = multi.getFile(name);
String ContentType = multi.getContentType(name);
if (fileName != null)
{
count ++;
%>
<font color="red">您上傳的第<%= count %>個文件:</font><br>
文件名:<%= fileName %><br>
文件類型:<%= ContentType %><br>
文件描述:<%= fileDescription[count-1] %><br><br>
<%
}
}
%>
三、運行結果
程序已在NetBeans IDE 5.0+j2sdk1.5環境調試成功,服務器軟件采用Tomcat 5。
客戶端軟件運行效果如圖1所示。

圖1 客戶端顯示界面
1.在圖1中點擊“生成密鑰對”按鈕,即在當前目錄生成公鑰文件sigPublicKey.dat和私鑰文件sigPrivateKey.dat,生成完畢后會彈出密鑰生成成功消息框,私鑰文件自己保留,公鑰文件公開發布。
2.在圖1中,選擇原文件和私鑰文件,輸入保存的簽名文件名,然后點擊“生成簽名文件”按鈕,生成指定的數字簽名文件。
3.文件上傳頁面fileload.html(如圖2所示),在上傳時,將原文件和生成的簽名文件一同打包上傳。

圖2 上傳頁面
4.接收方同樣運行客戶端軟件,選擇原文件和發送方的公鑰文件,發送方的簽名文件,然后點擊“文件簽名驗證”按鈕,如果驗證通過,則彈出消息確認框(如圖3所示),如驗證失敗,則彈出驗證失敗消息框。

圖 3 消息確認框
四、結語
目前,數字簽名技術已成為計算機網絡信息安全方面的一項重要技術,用于數字簽名的公開密鑰體制除了本文用到的DSA算法,常用的算法還有RSA算法和橢圓曲線算法。本文所闡述數字簽名技術主要用于網上申請文件方面,當然此程序同樣適用于各類電子文件的數字簽名。
參考文獻
1.張煥國.密碼學引論.武漢大學出版社,2003
2.柳永坡.JSP應用開發技術.人民郵電出版社,2005
|