自己封装的数字证书签名及签名验证方法,附带生成证书的语句

Posted 新手娃娃菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己封装的数字证书签名及签名验证方法,附带生成证书的语句相关的知识,希望对你有一定的参考价值。

如果java环境搭建好,注释中内容可以新建一个bat来执行,或者直接粘贴到黑屏执行,即可生成私钥和公钥的证书

REM # create keystore file
keytool -genkey -dname "CN=Test Bank, OU=Test, O=Test, L=BeiJing, ST=BeiJing, C=CN" -alias testAlias -keyalg RSA -keysize 1024 -keystore TestPrivate.jks -keypass 12345678 -storepass 12345678 -validity 365

REM # export cert file
keytool -export -alias testAlias -file TestPublic.cer -keystore TestPrivate.jks -storepass 12345678


package com.develop.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class SignUtil {
    /**
    
    如果java环境搭建好,注释中内容可以新建一个bat来执行,或者直接粘贴到黑屏执行,即可生成私钥和公钥的证书
    
    REM # create keystore file
    keytool -genkey -dname "CN=Test Bank, OU=Test, O=Test, L=BeiJing, ST=BeiJing, C=CN" -alias testAlias -keyalg RSA -keysize 1024 -keystore TestPrivate.jks -keypass 12345678 -storepass 12345678 -validity 365

    REM # export cert file
    keytool -export -alias testAlias -file TestPublic.cer  -keystore TestPrivate.jks -storepass 12345678
    
    
    **/
    
    private static String defaultAlgorithm = "SHA1withRSA";//默认签名算法
    private static String defaultKeystoreType = "JKS";//私钥证书类型
    
    private static String defaultCertificateType = "x.509";//公钥证书类型

    /**
     * 读取私钥证书,并对原数据进行签名
     * @param srcByte 原数据的byte
     * @param algorithm 要对原数据进行签名的算法  无设置默认SHA1withRSA
     * @param keystoreType 私钥证书类型  无设置默认JKS
     * @param keystorePath 私钥证书路径
     * @param keystorePwd 私钥证书密码
     * @return byte[] 返回签名后byte
     */
    public static byte[] sign(byte[] srcByte,String algorithm,String keystoreType,String keystorePath,String keystorePwd){
        byte[] rsByte = null;//返回参数
        
        if(srcByte==null){
            System.out.println("原数据byte为空!");
            return rsByte;
        }
        
        if(keystorePwd==null){
            System.out.println("私钥证书密码为空!");
            return rsByte;
        }
        if(algorithm==null||"".equals(algorithm)){
            algorithm = defaultAlgorithm;//如果传入算法类型为空,初始化类型
        }
        if(keystoreType==null||"".equals(keystoreType)){
            keystoreType = defaultKeystoreType;//如果船驶入证书类型为空,初始化证书类型
        }
        
        //读取私钥证书文件
        FileInputStream stream = null;
        try {
            stream = new FileInputStream(keystorePath);
        } catch (FileNotFoundException e) {
            System.out.println("未找到私钥证书文件!");
            e.printStackTrace();
        }
        
        if(stream==null){
            return rsByte;
        }
        
        //load私钥证书信息,获取私钥
        PrivateKey privateKey = null;
        try {
            KeyStore keyStore = KeyStore.getInstance(keystoreType);
            keyStore.load(stream, keystorePwd.toCharArray());
            Enumeration<String> aliases = keyStore.aliases();
            
            String alias = null;
            while(aliases.hasMoreElements()){
                String element = aliases.nextElement();
                if(keyStore.isKeyEntry(element)){
                    alias = element;
                    break;
                }
            }

            privateKey = (PrivateKey)keyStore.getKey(alias, keystorePwd.toCharArray());
            
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(stream!=null){
                try {
                    stream.close();
                    stream = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        //获取签名对象进行签名
        try {
            Signature signature=Signature.getInstance(algorithm);
            signature.initSign(privateKey);
            signature.update(srcByte);
            rsByte = signature.sign();
        } catch (NoSuchAlgorithmException e) {
            System.out.println("没有此签名算法!");
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            System.out.println("无效的私钥!");
            e.printStackTrace();
        } catch (SignatureException e) {
            System.out.println("对原数据进行签名异常!");
            e.printStackTrace();
        }
        
        return rsByte;
    }
    
    /**
     * 读取私钥证书,并对原数据进行签名
     * @param srcData 原数据
     * @param algorithm 要对原数据进行签名的算法  无设置默认SHA1withRSA
     * @param keystoreType 私钥证书类型  无设置默认JKS
     * @param keystorePath 私钥证书路径
     * @param keystorePwd 私钥证书密码
     * @return String 证书签名后进行base64encode的字符串
     */
    public static String sign(String srcData,String algorithm,String keystoreType,String keystorePath,String keystorePwd){
        String signedData = "";
        if(srcData==null||"".equals(srcData)){
            System.out.println("原数据为空!");
            return signedData;
        }
        byte[] srcByte = srcData.getBytes();
        byte[] rsByte = sign(srcByte, algorithm, keystoreType, keystorePath, keystorePwd);
        
        if(rsByte==null){
            System.out.println("私钥证书签名返回byte为空!");
            return signedData;
        }
        
        signedData = new BASE64Encoder().encodeBuffer(rsByte);
        
        return signedData;
    }
    
    /**
     * 读取公钥证书的公钥,验证签名前后byte是否正确
     * @param srcByte 原数据
     * @param signedByte 签名后数据
     * @param algorithm 算法  无设置默认SHA1withRSA
     * @param certificateType 公钥证书类型  无设置默认x.509
     * @param certificatePath 公钥证书路径
     * @return true 验证通过     false 验证失败
     */
    public static boolean verify(byte[] srcByte,byte[] signedByte,String algorithm,String certificateType,String certificatePath){
        boolean result = false;
        
        if(srcByte==null){
            System.out.println("传入的原数据byte为空!");
            return result;
        }
        if(signedByte==null){
            System.out.println("传入的签名数据byte为空!");
            return result;
        }
        
        if(algorithm==null||"".equals(algorithm)){
            algorithm = defaultAlgorithm;
        }
        if(certificateType==null||"".equals(certificateType)){
            certificateType = defaultCertificateType;
        }
        
        //读取公钥证书文件
        FileInputStream stream = null;
        try {
            stream = new FileInputStream(certificatePath);
        } catch (FileNotFoundException e) {
            System.out.println("未找到公钥证书文件!");
            e.printStackTrace();
        }
        
        if(stream==null){
            return result;
        }
        
        //获取公钥证书的公钥
        PublicKey publicKey = null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance(certificateType);
            Certificate certificate = null;
            if("x.509".equals(certificateType)){
                certificate = (X509Certificate)certificateFactory.generateCertificate(stream);
            }else{
                //TODO 待扩展
            }
            if(certificate==null){
                return result;
            }
            publicKey = certificate.getPublicKey();
        } catch (CertificateException e) {
            e.printStackTrace();
        }finally{
            if(stream!=null){
                try {
                    stream.close();
                    stream = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        //获取签名对象进行签名
        try {
            Signature signature=Signature.getInstance(algorithm);
            signature.initVerify(publicKey);
            signature.update(srcByte);
            result = signature.verify(signedByte);
        } catch (NoSuchAlgorithmException e) {
            System.out.println("没有此签名算法!");
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            System.out.println("无效的公钥!");
            e.printStackTrace();
        } catch (SignatureException e) {
            System.out.println("对原数据进行验签异常!");
            e.printStackTrace();
        }

        return result;
    }
    
    /**
     * 读取公钥证书的公钥,验证签名串是否正确
     * @param srcData 签名前数据字符串
     * @param signedData 签名后数据字符串
     * @param algorithm 签名使用的算法   无设置默认SHA1withRSA
     * @param certificatePath 公钥证书路径
     * @return true 验证通过     false 验证失败
     */
    public static boolean verify(String srcData,String signedData,String algorithm,String certificatePath){
        boolean result = false;
        if(srcData==null||"".equals(srcData)){
            System.out.println("传入的原数据为空!");
            return result;
        }
        if(signedData==null||"".equals(signedData)){
            System.out.println("传入的签名后数据为空!");
            return result;
        }
        byte[] srcByte = srcData.getBytes();
        byte[] signedByte = null;
        try {
            signedByte = new BASE64Decoder().decodeBuffer(signedData);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        result = verify(srcByte, signedByte, algorithm, null, certificatePath);
        return result;
    }
    
    
    public static void main(String[] args) {
        String srcData = "test测试数据";
        String rsData = sign(srcData, "SHA1withRSA", "jks", "D:\\test\\TestPrivate.jks", "12345678");
        System.out.println(rsData);
        
        boolean result = verify(srcData, rsData, "SHA1withRSA", "D:\\test\\TestPublic.cer");
        System.out.println(result);
    }
    
}

 

以上是关于自己封装的数字证书签名及签名验证方法,附带生成证书的语句的主要内容,如果未能解决你的问题,请参考以下文章

自签名证书颁发及验证

无需苹果企业证书签名,IPA证书签名,ios证书签名,不用签名证书将网页封装成苹果描述文件

net6 项目搭建及引用框架记录(log4net,autofac,exception,api result,jwt,efcore)八使用pfx证书RSA方式生成jwt签名的Token,公钥验证签名

net6 项目搭建及引用框架记录(log4net,autofac,exception,api result,jwt,efcore)八使用pfx证书RSA方式生成jwt签名的Token,公钥验证签名

Tomcat 服务器/客户端自签名 SSL 证书

https 的证书验证