前言
- 数字签名(又称公钥数字签名)是只有发送方才能产生的无法伪造的数字串,是对发送者发送信息真实性的有效证明。
- 数字签名主要是保证数据有效性(验证是谁发的)和完整性(验证信息是否被篡改)。
- 数字签名是非对称加密和数字摘要技术的应用。
数字签名流程
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/110480569PrivateKey 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));}
}