JAVA加密算法數(shù)字簽名實(shí)現(xiàn)原理詳解
所謂數(shù)字簽名就是信息發(fā)送者用其私鑰對(duì)從所傳報(bào)文中提取出的特征數(shù)據(jù)(或稱數(shù)字指紋)進(jìn)行 RSA 算法操作,以保證發(fā)信人無(wú)法抵賴曾發(fā)過該信息(即不可抵賴性),同時(shí)也確保信息報(bào)文在經(jīng)簽名后末被篡改(即完整性)。當(dāng)信息接收者收到報(bào)文后,就可以用發(fā)送者的公鑰對(duì)數(shù)字簽名進(jìn)行驗(yàn)證。
在數(shù)字簽名中有重要作用的數(shù)字指紋是通過一類特殊的散列函數(shù)(HASH 函數(shù))生成的,對(duì)這些 HASH 函數(shù)的特殊要求是:
1:接受的輸入報(bào)文數(shù)據(jù)沒有長(zhǎng)度限制;
2:對(duì)任何輸入報(bào)文數(shù)據(jù)生成固定長(zhǎng)度的摘要(數(shù)字指紋)輸出
3:從報(bào)文能方便地算出摘要;
4:難以對(duì)指定的摘要生成一個(gè)報(bào)文,而由該報(bào)文反推算出該指定的摘要;
5:兩個(gè)不同的報(bào)文難以生成相同的摘要
代表: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() {
// 數(shù)字簽名生成密鑰
// 第一步生成密鑰對(duì),如果已經(jīng)生成過 , 本過程就可以跳過
// 對(duì)用戶來講 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 {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("myprikey.dat"));
PrivateKey myprikey = (PrivateKey) in.readObject();
in.close();
String myinfo = "這是我的信息"; // 要簽名的信息
// 用私鑰對(duì)信息生成數(shù)字簽名
Signature signet = 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è)文件中
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("簽名并生成文件失敗");
}
// 第三步 獲得信息檢查
// 其他人通過公共方式得到此戶的公鑰和文件
// 其他人用此戶的公鑰 , 對(duì)文件進(jìn)行檢查 , 如果成功說明是此用戶發(fā)布的信息 .
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();
}
;
}
// 生成一對(duì)文件 myprikey.dat 和 mypubkey.dat 私鑰和公鑰
// 公鑰要用戶發(fā)送 ( 文件 , 網(wǎng)絡(luò)等方法 ) 給其它用戶 , 私鑰保存在本地
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("寫入對(duì)象 prikeys ok");
out = new ObjectOutputStream(new FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
System.out.println("寫入對(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();
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot結(jié)果封裝和異常攔截的實(shí)現(xiàn)示例
SpringBoot 項(xiàng)目中,我們通常需要將結(jié)果數(shù)據(jù)封裝成特定的格式,以方便客戶端進(jìn)行處理,本文主要介紹了SpringBoot?優(yōu)雅的結(jié)果封裝和異常攔截,感興趣的可以了解一下2023-08-08
解決springboot 獲取form-data里的file文件的問題
這篇文章主要介紹了解決springboot 獲取form-data里的file文件的問題的相關(guān)資料,這里提供了詳細(xì)的解決步驟,需要的朋友可以參考下2017-07-07
SpringBoot項(xiàng)目實(shí)戰(zhàn)之加載和讀取資源文件
在項(xiàng)目的開發(fā)中,我們知道的是SpringBoot框架大大減少了我們的配置文件,但是還是留下了一個(gè)application.properties文件讓我們可以進(jìn)行一些配置,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目實(shí)戰(zhàn)之加載和讀取資源文件的相關(guān)資料,需要的朋友可以參考下2021-10-10
在idea中將java項(xiàng)目中的單個(gè)類打包成jar包操作
這篇文章主要介紹了在idea中將java項(xiàng)目中的單個(gè)類打包成jar包操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
SpringBoot+Idea熱部署實(shí)現(xiàn)流程解析
這篇文章主要介紹了SpringBoot+Idea熱部署實(shí)現(xiàn)流程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

