摘 要 在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
|