前言
- 數字簽名(又稱公鑰數字簽名)是隻有發送方纔能產生的無法僞造的數字串,是對發送者發送信息真實性的有效證明。
- 數字簽名主要是保證數據有效性(驗證是誰發的)和完整性(驗證信息是否被篡改)。
- 數字簽名是非對稱加密和數字摘要技術的應用。
數字簽名流程
A爲客戶端,C爲服務端;
A寫郵件給C過程:
- A用公鑰對郵件加密,C收到郵件後用私鑰進行解密;
C寫郵件給A過程:
- C寫好郵件,用hash函數生成郵件的摘要,將摘要附在郵件上面,這就完成了數字簽名,然後,C再使用私鑰加密,最後發送給A;
- A收到郵件後,先把數字簽名取下來,然後用公鑰解密,若取下的數字簽名中的摘要和A的一樣,則可判斷數據是C發送的。再對郵件使用hash函數,將得到的結果與上一步得到的摘要對比,若兩者一致,則可判斷數據沒有被篡改過;
數字證書
數字證書(CA)是一個權威的證書籤發機構。
爲了防止公鑰被盜竊,安全起見,服務期端C將自己的公鑰去證書中心做個認證,過程時CA證書中心會將它的私鑰對服務端C的公鑰和一些相關信息一起加密,生成數字證書;
- 服務端C拿到數字證書後,在簽名的同時,將數字證書一起發給客戶端A;
- A收到郵件後,用數字證書CA的公鑰解開數字證書,就可以拿到服務端C的公鑰,這樣就可以判斷數字簽名是否是服務端A的;
簽名與驗籤代碼實現
package com.cao.cipher.signature;
import com.cao.cipher.rsa.RsaDemo03;
import org.apache.tomcat.util.codec.binary.Base64;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
/**
* @author:秋一葉
* @date:2020-11-18 17:59
* 數字簽名,驗籤
*/
public class SignatureDemo {
public static void main(String[] args) throws Exception{
String input = "原文";
//獲取私鑰,公鑰
//RsaDemo03類在上一篇博客中:https://blog.csdn.net/qq_36335426/article/details/110480569
PrivateKey privateKey = RsaDemo03.getPrivateKey("a.pri", "RSA");
PublicKey publicKey = RsaDemo03.getPublicKey("a.pub", "RSA");
//簽名
String signaturedData = getSignature(input, "sha256withrsa", privateKey);
System.out.println("生成簽名後:" + signaturedData);
//驗籤
boolean b = verifySignature(input, "sha256withrsa", publicKey, signaturedData);
System.out.println("驗簽結果:" + b);
}
/**
* 生成簽名
* @param input 原文
* @param algorithm 加密算法
* @param privateKey 私鑰
* @return
* @throws Exception
*/
private static String getSignature(String input, String algorithm, PrivateKey privateKey) throws Exception{
//獲取簽名對象
Signature signature = Signature.getInstance(algorithm);
//初始化簽名
signature.initSign(privateKey);
//傳入原文
signature.update(input.getBytes());
//開始簽名
byte[] sign = signature.sign();
//對簽名進行Base64編碼
return Base64.encodeBase64String(sign);
}
/**
* 校驗簽名
* @param input
* @param algorithm
* @param publicKey
* @param signaturedData
* @return
* @throws Exception
*/
private static boolean verifySignature(String input, String algorithm, PublicKey publicKey, String signaturedData) throws Exception{
//獲取簽名對象
Signature signature = Signature.getInstance(algorithm);
//初始化簽名
signature.initVerify(publicKey);
//傳入原文
signature.update(input.getBytes());
//校驗數據
return signature.verify(Base64.decodeBase64(signaturedData));
}
}