数字签名与验签

前言


  • 数字签名(又称公钥数字签名)是只有发送方才能产生的无法伪造的数字串,是对发送者发送信息真实性的有效证明。
  • 数字签名主要是保证数据有效性(验证是谁发的)和完整性(验证信息是否被篡改)。
  • 数字签名是非对称加密和数字摘要技术的应用。

数字签名流程


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));
    }
}
上一篇:MD5withRSA算法加密


下一篇:ngrok内网穿透教程