隨著計(jì)算機(jī)網(wǎng)絡(luò)技術(shù)和軟件技術(shù)的蓬勃發(fā)展,以及internet的廣泛應(yīng)用對傳統(tǒng)的工作方式產(chǎn)生的巨大沖擊,電子政務(wù)(E-government)系統(tǒng)就在這樣的環(huán)境下應(yīng)運(yùn)而生了。電子政務(wù)的所有活動都是政府行為,要求具有高度的可靠性和安全性。數(shù)字簽名技術(shù)這種能保證數(shù)據(jù)的完整性、機(jī)密性、抗否定性的信息安全技術(shù)毫無疑問將會在電子政務(wù)系統(tǒng)中得到廣泛的應(yīng)用。由于java在網(wǎng)絡(luò)編程中的適用性,以及java的安全系統(tǒng)結(jié)構(gòu)的日益完善和目前java開發(fā)網(wǎng)絡(luò)安全軟件的便利性,因此在電子政務(wù)系統(tǒng)中用java來實(shí)現(xiàn)數(shù)字簽名會具有更好的現(xiàn)實(shí)意義。
數(shù)字簽名的流程
數(shù)字簽名是相對于手書簽名而言的,是指采用一定的數(shù)據(jù)交換協(xié)議,使用密碼算法對待發(fā)的數(shù)據(jù)(如文件、合同、通知等)進(jìn)行加密處理后,生成一段信息,附著在原文上一起發(fā)送,這段信息類似現(xiàn)實(shí)中的簽名或印章,接收方對其進(jìn)行驗(yàn)證,判斷發(fā)送者的身份和原文真?zhèn)巍?/p>
數(shù)字簽名主要是采用非對稱加密算法,先采用單向Hash函數(shù),將待發(fā)送的數(shù)據(jù)生成消息摘要MD_1,發(fā)送方使用自己的私鑰對消息摘要加密生成數(shù)字簽名,將數(shù)字簽名附著在原文上一起發(fā)送。接收方收到消息以后,先用發(fā)送方的公鑰將簽名解密,得到消息摘要。然后利用接收的原數(shù)據(jù)進(jìn)行單向Hash函數(shù)的計(jì)算,得到消息摘要MD_2進(jìn)行驗(yàn)證,如果MD_1=MD_2,說明簽名成功。
數(shù)字簽名的流程如圖(一)所示:
從流程圖可以看出,數(shù)字簽名包括簽名算法和驗(yàn)證算法,目前主要使用的簽名算法有RSA和DSA。
從數(shù)字簽名的原理和流程圖我們可以看出,數(shù)字簽名主要有以下幾方面的功能:
(1)保證了信息的完整性。根據(jù)Hash函數(shù)的性質(zhì),一旦原始信息被改動,所生成的數(shù)字摘要就會發(fā)生很大的變化。因此,通過這種方式,能防止原始信息被篡改。
(2)抗否認(rèn)性。使用公開密鑰的加密算法,由于只有發(fā)送方一人擁有私鑰,因此,發(fā)送方不能否認(rèn)發(fā)送過信息。
(3)防止接收方偽造一份報(bào)文,聲稱來自于發(fā)送方。
java在實(shí)現(xiàn)數(shù)字簽名方面的優(yōu)勢
java在實(shí)現(xiàn)數(shù)字簽名方面有很大的優(yōu)勢,主要表現(xiàn)在以下幾個方面:
1、Java平臺為安全和加密服務(wù)提供了兩組API:JCA和JCE;
2、JCA (Java Cryptography Architecture)提供基本的加密框架,如證書、數(shù)字簽名、消息摘要和密鑰對產(chǎn)生器;
3、JCE在JCA的基礎(chǔ)上作了擴(kuò)展,包括加密算法、密鑰交換、密鑰產(chǎn)生和消息鑒別服務(wù)等接口。
在電子政務(wù)系統(tǒng)中使用混合密碼體制來實(shí)現(xiàn)數(shù)字簽名技術(shù)
在電子政務(wù)系統(tǒng)中如果在數(shù)字簽名時原文在網(wǎng)絡(luò)上以明文傳輸,就不能保證原始信息的機(jī)密性,而要保證原始信息的機(jī)密性,就需要對待發(fā)送的原始信息實(shí)行加密運(yùn)算,若對原文使用非對稱密碼算法,由于使用非對稱密碼算法在解密時運(yùn)算量很大,將會影響運(yùn)算速度。所以,選擇使用對稱密碼算法對原文進(jìn)行加密,而用非對稱的密碼算法來實(shí)現(xiàn)數(shù)字簽名技術(shù),使用這種混合密碼體制,既能實(shí)現(xiàn)數(shù)字簽名,保證了在傳輸過程中原文機(jī)密性,又能提高運(yùn)算效率。
使用混合密鑰的數(shù)字簽名流程如圖(二)所示:
用java語言來實(shí)現(xiàn)混合密鑰的數(shù)字簽名
前面已經(jīng)提到了java2為實(shí)施安全策略提供了很多機(jī)制,因此在電子政務(wù)中要實(shí)現(xiàn)數(shù)字簽名選用java作為軟件的開發(fā)平臺是一個可行的方案,下面就給出一個實(shí)例的主要算法說明用java2是怎樣實(shí)現(xiàn)數(shù)字簽名的。因?yàn)槭怯迷陔娮诱?wù)系統(tǒng)中,接收和發(fā)送文件的雙方通常都比較固定,這里就不考慮公鑰傳送的安全問題,先假定接收方使用的公鑰即為發(fā)送方使用的私鑰所對應(yīng)的公鑰,算法中生成消息摘要的算法為MD5,簽名算法使用RSA,對原文進(jìn)行對稱加密算法使用DES:
Java2中需要用到的主要的類基本上都封裝在java.security.*和javax.crypto.*兩個包中。
(1)引入需要用的java包
/*包含輸入輸出的類*/
Import java.io.*;
/*包含密鑰對生成器類、密鑰管理類、簽名類*/
Import java.security.*;
/*包含各種密碼算法類如:DES和RSA等*/
Import javax.crypto.*;
(2)發(fā)送方的代碼( 假設(shè)要傳送的數(shù)據(jù)是保存在文件info.dat中的):
/*生成RSA算法的公鑰pubKey和私鑰priKey,這里假定公鑰生成以后是通過第三方安全的發(fā)送給接收方的*/
KeyPairGenerator DoublekeyGen = KeyPairGenerator.getInstance(“RSA”);
DoublekeyGen.init(1024);
KeyPair DoubleKey = DoublekeyGen.generateKeyPair();
PrivateKey priKey = DoubleKey.getPrivate();
PublicKeypubKey = DoubleKey.getpublic();
/* 將公鑰pubKey保存在文件pubKey.dat文件中,供接收方使用*/ ObjectOutputStream out = new.ObjectOutputStream(newFileOutputStream(“pubKey.dat”);
out.writeObject(pubKey);
out.close();
/*生成DES算法的密鑰Key*/
KeyPairGenerator SinglekeyGen = KeyGenerator.getInstance(“DES”);
SinglekeyGen.init(64);
Key SingleKey = SinglekeyGen.generateKey();
/*從文件info.dat讀出需要傳輸?shù)脑紨?shù)據(jù)并保存在數(shù)組info_Plain[ ]中*/
ObjectInputStream in=new ObjectInputStream(new FileInputStream(“info.dat”));
byte[ info_Plain=(byte[ ])in.readObject();
in.close();
/*將待傳輸?shù)脑夹畔⑸上⒄狹D_1*/
MessageDigest messageDigest = MessageDigest.getInstance(“MD5”);
messageDigest.update(info_Plain);
byte[ ] MD_1 = messageDigest.digest();
/* 將待傳輸?shù)男畔⒂肈ES加密,并將加密后的數(shù)據(jù)保存在數(shù)組Des_info[ ]中*/
Ciphercipher = cipher.getInstance(“DES”);cipher.init(Cipher.ENCRYPT_MODE,SingleKey);
byte[ ] Des_info[ ] = cipher.doFinal(info_plain);
/* 將消息摘要MD_1[ ]和對稱密鑰SingleKey合并到字節(jié)數(shù)組MD_Key[ ]中,并用RSA算法中的私鑰對該數(shù)組加密并保存在數(shù)組Rsa_sign[ ]中形成了數(shù)字簽名*/
合并數(shù)組的算法略(主要就是通過循環(huán)將對稱密鑰添加到消息摘要數(shù)組的后面,形成一個新的數(shù)組MD_Key[ ],對稱密鑰要通過強(qiáng)制類型轉(zhuǎn)化為byte類型)
Cipher cipher = cipher.getInstance(“RSA”);
cipher.init(Cipher.ENCRYPT_MODE, priKey);
byte[ ]Rsa_sign[ ] = cipher.doFinal(MD_Key);
/*將需要傳輸?shù)脑牡拿芪暮蛿?shù)字簽名寫到文件En_info.dat中,En_info.dat即為在網(wǎng)上傳輸?shù)男畔?/
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(“En_info.dat));
Out.writeobject(Des_info);
Out.writeobject(Rsa_sign);。
Out.close();
(3)接收方的代碼
接受方收到文件En_info.dat,該文件信息由兩部分組成○1原文的密文:保存數(shù)組Des_info[ ];○2發(fā)送方的數(shù)字簽名:保存在Rsa_sign[ ]數(shù)組中;并從pubKey.dat文件中將公鑰讀出且保存在變量PubKey中。
/*從文件En_info.dat中讀出原文的密文和數(shù)
字簽名兩個數(shù)組*/
此部分算法略
/*將數(shù)字簽名保存在Rsa_sign[ ]數(shù)組中用發(fā)送方的公鑰解密得到消息摘要和對稱密鑰組成的數(shù)組MD_Key[ ]*/
公鑰解密的算法略(解密和加密算法基本相同)
Int len = MD_Key.length();
Byte[ ]MD_1 = new Byte[ ];
Byte[ ]Key =new Byte[ ]
For (int i=0; i<128;i++)/*因?yàn)橛肕D5產(chǎn)生的數(shù)字摘要為128位*/
MD_1[i]=Md_Key[i];/*將摘要部分提取出來賦給數(shù)組MD_1*/
/*數(shù)組中的128位以后的元素即為對稱密鑰*/
While(i {Key[i]=Md_Key[i];}/*將對稱密鑰提取出來賦給數(shù)組Key[ ]*/ Key SingleKey = (PrivateKey)key; /*將對稱密鑰強(qiáng)制類型轉(zhuǎn)換為key型*/ /*得到對稱密鑰后,通過DES的解密算法將密文變成明文,再將明文用MD5算法生成消息摘要并保存在數(shù)組MD_2[ ]中*/ 解密和生成消息摘要的算法略 /*將MD_1[ ] 和MD_2[ ]做比較,若相等,則簽名正確*/ For(int i=0;i<128;i++) { if MD_1[i] != MD_2[i] { System.out.println(“Signature error!”); System.exit.( ); } } System.out.println(“Signature success!”); 由于只是給出了主要的算法,沒有考慮在程序的執(zhí)行過程中可能出現(xiàn)的異常情況以及一些基本的輸入輸出語句。