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