JAVA加密演算法數字簽名實現原理詳解
阿新 • • 發佈:2020-10-21
所謂數字簽名就是資訊傳送者用其私鑰對從所傳報文中提取出的特徵資料(或稱數字指紋)進行 RSA 演算法操作,以保證發信人無法抵賴曾發過該資訊(即不可抵賴性),同時也確保資訊報文在經簽名後末被篡改(即完整性)。當資訊接收者收到報文後,就可以用傳送者的公鑰對數字簽名進行驗證。
在數字簽名中有重要作用的數字指紋是通過一類特殊的雜湊函式(HASH 函式)生成的,對這些 HASH 函式的特殊要求是:
1:接受的輸入報文資料沒有長度限制;
2:對任何輸入報文資料生成固定長度的摘要(數字指紋)輸出
3:從報文能方便地算出摘要;
4:難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要;
5:兩個不同的報文難以生成相同的摘要
代表:DSA
程式碼如下
package test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; public class DSA { public static void main(String[] args) { try { DSA my = new DSA(); my.run(); } catch (Exception e) { e.printStackTrace(); } } public void run() { // 數字簽名生成金鑰 // 第一步生成金鑰對,如果已經生成過,本過程就可以跳過 // 對使用者來講 myprikey.dat 要儲存在本地,而 mypubkey.dat 給釋出給其它使用者 if ((new java.io.File("myprikey.dat")).exists() == false) { if (generatekey() == false) { System.out.println("生成金鑰對敗"); return; } } // 第二步,此使用者 // 從檔案中讀入私鑰,對一個字串進行簽名後儲存在一個檔案 (myinfo.dat) 中 // 並且再把 myinfo.dat 傳送出去,為了方便數字簽名也放進了 myifno.dat 檔案中,當然也可分別傳送 try { ObjectInputStream in = new ObjectInputStream(new FileInputStream("myprikey.dat")); PrivateKey myprikey = (PrivateKey) in.readObject(); in.close(); String myinfo = "這是我的資訊"; // 要簽名的資訊 // 用私鑰對資訊生成數字簽名 Signature signet = Signature.getInstance("DSA"); signet.initSign(myprikey); signet.update(myinfo.getBytes()); byte[] signed = signet.sign(); // 對資訊的數字簽名 System.out.println("signed( 簽名內容 )=" + byte2hex(signed)); // 把資訊和數字簽名儲存在一個檔案中 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("myinfo.dat")); out.writeObject(myinfo); out.writeObject(signed); out.close(); System.out.println("簽名並生成檔案成功"); } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("簽名並生成檔案失敗"); } // 第三步 獲得資訊檢查 // 其他人通過公共方式得到此戶的公鑰和檔案 // 其他人用此戶的公鑰,對檔案進行檢查,如果成功說明是此使用者釋出的資訊 . try { ObjectInputStream in = new ObjectInputStream(new FileInputStream("mypubkey.dat")); PublicKey pubkey = (PublicKey) in.readObject(); in.close(); System.out.println(pubkey.getFormat()); in = new ObjectInputStream(new FileInputStream("myinfo.dat")); String info = (String) in.readObject(); byte[] signed = (byte[]) in.readObject(); in.close(); Signature signetcheck = 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(); } ; } // 生成一對檔案 myprikey.dat 和 mypubkey.dat 私鑰和公鑰 // 公鑰要使用者傳送 ( 檔案,網路等方法 ) 給其它使用者,私鑰儲存在本地 public boolean generatekey() { try { KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); keygen.initialize(512); KeyPair keys = keygen.genKeyPair(); PublicKey pubkey = keys.getPublic(); PrivateKey prikey = keys.getPrivate(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("myprikey.dat")); out.writeObject(prikey); out.close(); System.out.println("寫入物件 prikeys ok"); out = new ObjectOutputStream(new FileOutputStream("mypubkey.dat")); out.writeObject(pubkey); out.close(); System.out.println("寫入物件 pubkeys ok"); System.out.println("生成金鑰對成功"); return true; } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("生成金鑰對失敗"); 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(); } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。