概念:
1.數(shù)字摘要:解決在安全的通信環(huán)境下,保證信息的唯一的一種方式。通常使用MD5/SHA-1等算法完成摘要。一般比如大家在網(wǎng)上下載軟件光盤(pán)時(shí)都會(huì)看到一個(gè)MD5值就是起到這個(gè)數(shù)字摘要的作用。在網(wǎng)絡(luò)的環(huán)境中發(fā)送者把消息和數(shù)字摘要一同發(fā)送給接收者,接收者使用發(fā)送者相同的算法對(duì)消息加密,看是否與發(fā)送者發(fā)送過(guò)來(lái)的數(shù)字摘要相同,如果相同就證明消息沒(méi)有給篡改過(guò)。下面是一個(gè)最為簡(jiǎn)單的示例:
import java.security.*; public class myDigest { public static void main(String[] args) { myDigest my=new myDigest(); my.testDigest(); } public void testDigest() { try { String myinfo="我的測(cè)試信息"; //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5"); java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1"); alga.update(myinfo.getBytes()); byte[] digesta=alga.digest(); System.out.println("本信息摘要是:"+byte2hex(digesta)); //通過(guò)某中方式傳給其他人你的信息(myinfo)和摘要(digesta) 對(duì)方可以判斷是否更改或傳輸正常 java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1"); algb.update(myinfo.getBytes()); if (algb.isEqual(digesta,algb.digest())) { System.out.println("信息檢查正常"); } else { System.out.println("摘要不相同"); } } catch (java.security.NoSuchAlgorithmException ex) { System.out.println("非法摘要算法"); } } public String byte2hex(byte[] b) //二行制轉(zhuǎn)字符串 { String hs=""; String stmp=""; for (int n=0;n<b.length;n++) { stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length()==1) hs=hs+"0"+stmp; else hs=hs+stmp; if (n<b.length-1) hs=hs+":"; } return hs.toUpperCase(); } }
2.電子簽名:對(duì)數(shù)據(jù)信息的發(fā)生者身份的認(rèn)定,它是一種抽象的概念而不是一種具體技術(shù)。實(shí)現(xiàn)電子簽名的技術(shù)手段目前有多種,比如基于公鑰密碼技術(shù)的數(shù)字簽名;或用一個(gè)獨(dú)一無(wú)二的以生物特征統(tǒng)計(jì)學(xué)為基礎(chǔ)的識(shí)別標(biāo)識(shí),例如手印、聲音印記或視網(wǎng)膜掃描的識(shí)別;手書(shū)簽名和圖章的電子圖象的模式識(shí)別;表明身份的密碼代號(hào)(對(duì)稱算法);基于量子力學(xué)的計(jì)算機(jī)等等。
3.數(shù)字簽名:所謂數(shù)字簽名就是利用通過(guò)某種密碼運(yùn)算生成的一系列符號(hào)及代碼組成電子密碼進(jìn)行"簽名",來(lái)代替書(shū)寫(xiě)簽名或印章,對(duì)于這種電子式的簽名在技術(shù)上還可進(jìn)行算法驗(yàn)證,其驗(yàn)證的準(zhǔn)確度是在物理世界中與手工簽名和圖章的驗(yàn)證是無(wú)法相比的。一般實(shí)現(xiàn)數(shù)字簽名的方法是通過(guò)生成的密鑰對(duì)的私鑰對(duì)用戶生成的數(shù)字消息進(jìn)行DSA(Digital Signature Algorithm (DSA)是Schnorr和ElGamal簽名算法的變種,被美國(guó)NIST作為DSS(DigitalSignature Standard))加密實(shí)現(xiàn)的。實(shí)現(xiàn)代碼如下:
*/ import java.security.*; import java.security.spec.*; public class testdsa { public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception { testdsa my=new testdsa(); my.run(); } public void run() { //數(shù)字簽名生成密鑰 //第一步生成密鑰對(duì),如果已經(jīng)生成過(guò),本過(guò)程就可以跳過(guò),對(duì)用戶來(lái)講myprikey.dat要保存在本地 //而mypubkey.dat給發(fā)布給其它用戶 if ((new java.io.File("myprikey.dat")).exists()==false) { if (generatekey()==false) { System.out.println("生成密鑰對(duì)敗"); return; }; } //第二步,此用戶 //從文件中讀入私鑰,對(duì)一個(gè)字符串進(jìn)行簽名后保存在一個(gè)文件(myinfo.dat)中 //并且再把myinfo.dat發(fā)送出去 //為了方便數(shù)字簽名也放進(jìn)了myifno.dat文件中,當(dāng)然也可分別發(fā)送 try { java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat")); PrivateKey myprikey=(PrivateKey)in.readObject(); in.close(); // java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509); //java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec String myinfo="這是我的信息"; //要簽名的信息 //用私鑰對(duì)信息生成數(shù)字簽名 java.security.Signature signet=java.security.Signature.getInstance("DSA"); signet.initSign(myprikey); signet.update(myinfo.getBytes()); byte[] signed=signet.sign(); //對(duì)信息的數(shù)字簽名 System.out.println("signed(簽名內(nèi)容)="+byte2hex(signed)); //把信息和數(shù)字簽名保存在一個(gè)文件中 java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat")); out.writeObject(myinfo); out.writeObject(signed); out.close(); System.out.println("簽名并生成文件成功"); } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("簽名并生成文件失敗"); }; //第三步 //其他人通過(guò)公共方式得到此戶的公鑰和文件 //其他人用此戶的公鑰,對(duì)文件進(jìn)行檢查,如果成功說(shuō)明是此用戶發(fā)布的信息. // try { java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat")); PublicKey pubkey=(PublicKey)in.readObject(); in.close(); System.out.println(pubkey.getFormat()); in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat")); String info=(String)in.readObject(); byte[] signed=(byte[])in.readObject(); in.close(); java.security.Signature signetcheck=java.security.Signature.getInstance("DSA"); signetcheck.initVerify(pubkey); signetcheck.update(info.getBytes()); if (signetcheck.verify(signed)) { System.out.println("info="+info); System.out.println("簽名正常"); } else System.out.println("非簽名正常"); } catch (java.lang.Exception e) {e.printStackTrace();}; } //生成一對(duì)文件myprikey.dat和mypubkey.dat---私鑰和公鑰, //公鑰要用戶發(fā)送(文件,網(wǎng)絡(luò)等方法)給其它用戶,私鑰保存在本地 public boolean generatekey() { try { java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA"); // SecureRandom secrand=new SecureRandom(); // secrand.setSeed("tttt".getBytes()); //初始化隨機(jī)產(chǎn)生器 // keygen.initialize(576,secrand); //初始化密鑰生成器 keygen.initialize(512); KeyPair keys=keygen.genKeyPair(); // KeyPair keys=keygen.generateKeyPair(); //生成密鑰組 PublicKey pubkey=keys.getPublic(); PrivateKey prikey=keys.getPrivate(); java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat")); out.writeObject(prikey); out.close(); System.out.println("寫(xiě)入對(duì)象 prikeys ok"); out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat")); out.writeObject(pubkey); out.close(); System.out.println("寫(xiě)入對(duì)象 pubkeys ok"); System.out.println("生成密鑰對(duì)成功"); return true; } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("生成密鑰對(duì)失敗"); return false; }; } public String byte2hex(byte[] b) { String hs=""; String stmp=""; for (int n=0;n<b.length;n++) { stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length()==1) hs=hs+"0"+stmp; else hs=hs+stmp; if (n<b.length-1) hs=hs+":"; } return hs.toUpperCase(); } } 把他的公鑰的信息及簽名發(fā)給其它用戶
4.PKI(公鑰基礎(chǔ)設(shè)施):