当前位置:   article > 正文

java加密使用_java 实现sm2withsm3

java 实现sm2withsm3

概念

算法分类

对称加解密算法

加密和解密使用相同的秘钥,常见算法有DES、TDES、AES、SM4、RC2/4
在这里插入图片描述

非对称加解密算法

加密和解密使用不同的秘钥,公钥加密私钥解密,私钥加密公钥解密。常见算法有RSA、SM2、ECC

信息摘要算法

类似于hash,不可逆。常见的信息摘要算法有:MD2/4/5、SHA1/SHA224/SHA256/SHA384、SM3算法、MAC算法等
在这里插入图片描述

数字签名和消息验签

【数字签名】主要解决了两个核心问题:发送的消息是完整的,未被篡改的;接收的消息一定就是对应发送者发送的,别人无法仿制。前者体现的是数据的完整性,后者体现的是数据的不可抵赖性

数字签名过程

数字签名的应用公式如下所示,其中M表示消息原文,S表示数字签名,P表示非对称算法的私钥运算,D表示信息摘要算法的运算。

P(D(M [with any length])) = S [with fixed length]
  • 1

具体来说,发送方产生一个数据签名,需要经过以下几个步骤:

  • 使用【信息摘要算法】,对任意长度的信息原文做摘要运算,得到一段固定长度的摘要数据;
  • 如果该摘要数据的长度,没有达到非对称加密算法做加解密运算的输入长度,通常还需要使用填充 标准对摘要数据进行必要的填充,以达到非对称算法的运算条件;常用的填充标准有PKCS1-padding;
  • 使用【非对称加密算法】的私钥对填充后的摘要数据做加密运算,得到一段固定长度的数字签名;
  • 发送方将数字签名拼接在信息原文的尾部,一同发送给接收方,完成数据的单方向传输。

经过以上的步骤后,发送方就成功将信息原文和对应的数字签名,传递给了接收方;剩余的事,就是接收方对数据的验签操作。

消息验签过程

接收方收到发送方发送的数据报文(信息原文+数字签名)后,需要经历以下步骤来完成对报文消息的验签操作:

  • 首先,对数据报文进行分解,提取出信息原文部分和数字签名部分;

  • 与产生数字签名流程一样,使用相同的信息摘要算法对信息原文做摘要运算,得出消息原文的摘要D1;

  • 与产生数字签名流程相反,使用【非对称加密算法】中签名私钥对应的公钥对数字签名部分做解密 运算,解密后得到原始发送方发送的经填充后的摘要D2;
    与产生数字签名流程相反,使用相同的数据填充标准对摘要D2做去填充操作,得到原始消息的附带的摘要D3;

  • 比较D3和D1;如果两者相等,则表示对数字签名的验签是OK的,消息原文的数据是可信任的;反之,若D3不等于D1,则可以认为消息原文是不可信任的,数字签名中的【完整性】和【不可抵赖性】可能遭到了破坏;我们应该摒弃信息原文。

数字签名分类

数字签名算法,就是使用RSA、MD5、SM2、SHA、SM3等非对称算法和信息摘要算法进行混搭组合。数字签名算法的基本表示格式为:xxxWithYYYEncryption,其中xxx表示信息摘要算法,yyy表示非对称加密算法。常见有的以下几种:

  1. md5WithRSAEncryption:摘要运算采用MD5,非对称算法使用RSA;
  2. sha1WithRSAEncryption:摘要运算采用SHA1,非对称算法使用RSA;
  3. sha256WithRSAEncryption:摘要运算采用SHA256,非对称算法使用RSA;【常用】
  4. sm3WithSM2Encryption:摘要运算采用SM3,非对称算法使用SM2。

AES使用

生成秘钥

private static SecretKey generateKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128); // 秘钥长度为 128 位
        SecretKey secretKey = keyGenerator.generateKey();
        return secretKey;
    }

    /**
     * 二进制byte[]转十六进制string
     */
    public static String byteToHexString(byte[] bytes){
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String strHex=Integer.toHexString(bytes[i]);
            if(strHex.length() > 3){
                sb.append(strHex.substring(6));
            } else {
                if(strHex.length() < 2){
                    sb.append("0" + strHex);
                } else {
                    sb.append(strHex);
                }
            }
        }
        return  sb.toString();
    }

 public static void main(String[] args) {
	SecretKey secretKey = generateKey();
	System.out.println(byteToHexString(secretKey.getEncoded()));
	// b30957dc3e032f462866c917ff461088
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

使用秘钥加解密

// 使用hutool工具类
 String aesKey = "b30957dc3e032f462866c917ff461088";
 AES aes = SecureUtil.aes(aesKey.getBytes());
// 加密 encrpy = 9OqWLbnVeW/EsL6nevQfZQ==
 String encrypt = aes.encryptBase64("你好");
// 解密 decrypt = 你好
String decrypt = aes.decryptStr(encrypt);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

RSA使用

生成公私钥

public static void genKeyPair() {
        try {
            // 生成RSA密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024); // 设置密钥长度
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 获取公钥和私钥
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
            String publicKeyStr = encoder.encodeToString(publicKey.getEncoded());
            String privateKeyStr = encoder.encodeToString(privateKey.getEncoded());
            // 打印公钥和私钥
            System.out.println("公钥: " + publicKeyStr);
            System.out.println("私钥: " + privateKeyStr);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpG4FQWx7NMG8DQF1VJNegLBxtsyGjvQGdoMDl0mXnZT7eU+DrJ0G5nKdKI+CWr+1tvSR/1dIblYsJK+M1cotSjUN9l4qraxnFha5Js1ldfxcTlJuWOBgWAWVJ+C3hZGkzAo8F+0CCtwij9dpLd+5kbHpdBd9Vh3V0WgiBY2M3nQIDAQAB
私钥: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKkbgVBbHs0wbwNAXVUk16AsHG2zIaO9AZ2gwOXSZedlPt5T4OsnQbmcp0oj4Jav7W29JH/V0huViwkr4zVyi1KNQ32XiqtrGcWFrkmzWV1/FxOUm5Y4GBYBZUn4LeFkaTMCjwX7QIK3CKP12kt37mRsel0F31WHdXRaCIFjYzedAgMBAAECgYBOwnOwtC+dSzB46DJP5G/Utpaq9OH2+6FUA7mzkBFL+xiTvackfk0bIH29hwYjyF4hXRUxwKkxla2CoQEaNHX0Q6MX8LxdbEGzHypLuaB+gNQSbWT41AVLB+GmikLc6yaNKAbr6/rdGWCIYVzzf4XuH8FI4d0Zr2HV7vBeBCeV9QJBANu9LkT7+8VRI8fq/XE9gsMPQSO5gBqBprPvag32wwiP3Hsv/9BYs7BbvQASijgqzuoC74YJioPi66kyWS8XFjcCQQDFA2hCQjYHd6rzkjWBL707+scl4ddfIccl1YBE2fyM2djXzZEVkgqW4NILIZC3nMEvGoBiympdelnq7n0LQzbLAkEAwCosaZW4M3HnCbFenQZ+8VjIzZYvCn8xqxAHvlh7bWRqG6z5WVoJIoTHv2V3TPFa7FlO4Pg9E2OCVgA68CyPdwJAK9OVNuApysF5OxP0aReonhYshSXXVmdaOPVkwmxHvUGc9mzZcJX7WxMKRsWhvubVJthbZR6oSME2DYgeMwoxvwJAaxrWhkBVde5L1/nFaN19Yb4w82/z+lmjd2itjLybhe62Z1HqS86pc4rZKOaoegBeHT0omcCBMnGxYnYlYlgWpg==

  • 1
  • 2
  • 3

加密、加签、验签、解密

package com.echo.java8.encipher;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

/**
 * RSA签名,加解密处理核心文件,注意:密钥长度1024
 */
public class RSAHelper {
    @SuppressWarnings("unused")
    private static Logger LOGGER = LoggerFactory.getLogger(RSAHelper.class);

    /*
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    /*
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    /*
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /*
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    public static void genKeyPair() {
        try {
            // 生成RSA密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024); // 设置密钥长度
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 获取公钥和私钥
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
            String publicKeyStr = encoder.encodeToString(publicKey.getEncoded());
            String privateKeyStr = encoder.encodeToString(privateKey.getEncoded());
            // 打印公钥和私钥
            System.out.println("公钥: " + publicKeyStr);
            System.out.println("私钥: " + privateKeyStr);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * 签名字符串
     *
     * @param text       需要签名的字符串
     * @param privateKey 私钥(BASE64编码)
     * @param charset    编码格式
     * @return 签名结果(BASE64编码)
     * @throws Exception
     */
    public static String sign(String text, String privateKey, String charset) throws Exception {
        return sign(text, privateKey, charset, SIGNATURE_ALGORITHM);
    }

    public static String sign(String text, String privateKey, String charset,
                              String signatureAlgorithm) throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory;
        try {
            keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance(signatureAlgorithm);
            signature.initSign(privateK);
            signature.update(getContentBytes(text, charset));
            return Base64Utils.encodeToString(signature.sign());
        } catch (Exception e) {
            throw new Exception("RSA sign exception:" + e.getMessage());
        }
    }


    /**
     * 验签字符串
     *
     * @param text      需要签名的字符串
     * @param sign      客户签名结果
     * @param publicKey 公钥(BASE64编码)
     * @param charset   编码格式
     * @return 验签结果
     * @throws Exception
     */
    public static boolean verify(String text, String sign, String publicKey, String charset) throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory;
        try {
            keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicK = keyFactory.generatePublic(keySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicK);
            signature.update(getContentBytes(text, charset));
            return signature.verify(Base64Utils.decodeFromString(sign));
        } catch (Exception e) {
            LOGGER.warn("RSA verify exception", e);
            throw new Exception("RSA verify exception:" + e.getMessage());
        }
    }

    /**
     * <P>
     * 私钥解密
     * </p>
     *
     * @param encryptedData 已加密数据
     * @param privateKey    私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;

    }
    public static String decryptByPublicKey(String encryptedData, String publicKey) throws Exception {
        byte[] bytes = decryptByPublicKey(Base64Utils.decodeFromString(encryptedData), publicKey);
        return new String(bytes);
    }
    /**
     * <p>
     * 公钥解密
     * </p>
     *
     * @param encryptedData 已加密数据
     * @param publicKey     公钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }
    
    /**
     * <p>
     * 公钥加密
     * </p>
     *
     * @param data      源数据
     * @param publicKey 公钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey, String cipherArgs) throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = null;
        if (Objects.isNull(cipherArgs)) {
            cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        } else {
            cipher = Cipher.getInstance(cipherArgs);
        }
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;

    }


    /**
     * <p>
     * 私钥加密
     * </p>
     *
     * @param data       源数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;

    }

    /**
     * @param content
     * @param charset
     * @return
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    private static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }


    public static void main(String[] args) throws Exception {
        String text = "hello";
//        rsaKeyGenerate("test");
        String publicKeyStr = " MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLSTLXzr70geYHPD8uSLj8it7LvdZRz4hhYPHPQ6MvdJ9mLuooiXtXEwOgTWAIWtXXWL2EYoIo/AhaE3B91hpkIsXtdlotaMJSLv3vilZnd6nLISJXQiWJ7IKOShAByXJFGr8aT+blTQOwYUayKKXycXL1Sg1KINjJSiNKfZF+KwIDAQAB";
        String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAItJMtfOvvSB5gc8Py5IuPyK3su91lHPiGFg8c9Doy90n2Yu6iiJe1cTA6BNYAha1ddYvYRigij8CFoTcH3WGmQixe12Wi1owlIu/e+KVmd3qcshIldCJYnsgo5KEAHJckUavxpP5uVNA7BhRrIopfJxcvVKDUog2MlKI0p9kX4rAgMBAAECgYB7YDxEAqMMq99Yu1nvooURVeUhracg0maocxneELiEeZYUCixp+dWh/HqyzLbqz6MpXDaLBELtEMpJF30GSdcXWh+/9kN7IeWnlTZxmpc4FxeQydCGOJdgLv+GsR0ulYp4vH8L5cEDy6TZ4C7AHRv8KZOzrwBkZSTL1UayzIDncQJBAM267L4Tz51G/pxXsxjzMfM1mzgr/SvsWlj5OpwECYm7s2kGVxrVtdsCMj2rSYbjrR0TCZe7cKIXRR0lARIxTikCQQCtUfnBqoFHny5twGD/HlvDYoalnxxCYJJg+mBdR5s5ElMzkpjuKRWrvxTeroY+vPpL+7RHSU0qNCpXTvqmDQwzAkAVU817Hv6k5Vk7x/OvIHcLKYF/3z+NsCDlnGCxD9IVTzoYJyochA8oNyASOJGUxEGMBA84hZv1kcf+b3me8zGRAkBrC89jAskYEEOfu4rs5rYsRcT9s/jDMlwWE23DDv/azuueVbOonK1qxvi/1DDLvPImTc55nNdQ8qkYBYqfVj2rAkAnHEKLtgxWXreWRAbujoMgLOR2AEUyG7Vbw+0s/JPSU04DGex3Wj6/+bJQdejAiXUTJSTJjE69aHKwPKBx3fBN";

        byte[] bytes = encryptByPrivateKey(text.getBytes("UTF-8"), privateKeyStr);
        String s = Base64Utils.encodeToString(bytes);
        System.out.println("s:"+s);
        String sign = sign(s, privateKeyStr, "UTF-8");
        System.out.println(sign);
        System.out.println(verify(s, sign, publicKeyStr, "UTF-8"));


        System.out.println(decryptByPublicKey(s, publicKeyStr));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321

SM2使用

openssl生成RSA证书对,证书生成参考 密码:zsqq

将公钥和私钥证书文件转化为字符串存储

	// 将公钥文件转化为字符串
   public static String parsePubStr( String publicFile) throws Exception {
        InputStream is = new FileInputStream(publicFile);
        CertificateFactory cf = CertificateFactory.getInstance("x509");
        X509Certificate cerCert = (X509Certificate) cf.generateCertificate(is);
        // 生成PublicKey
        PublicKey publicKey = cerCert.getPublicKey();
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
        return publicKeyString;
    }
  // 将私钥文件转化为字符串
  public static String parsePriStr( String privateFile) throws Exception {
        InputStream is = new FileInputStream(privateFile);
        KeyStore tKeyStore = KeyStore.getInstance("PKCS12");
        tKeyStore.load(is, "ht123456".toCharArray());
        Enumeration e = tKeyStore.aliases();
        String tAliases = null;
        while (e.hasMoreElements()) {
            tAliases = (String) e.nextElement();
            break;
        }
        PrivateKey privateKey = (PrivateKey) tKeyStore.getKey(tAliases, "ht123456".toCharArray());
        Base64.Encoder encoder = Base64.getEncoder();
        String s = encoder.encodeToString(privateKey.getEncoded());
        return s;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

加密、加签、验签、解密

package com.echo.java8.encipher;

import cn.hutool.core.codec.Base64;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECFieldFp;
import java.security.spec.EllipticCurve;


/**
 * @description:
 * @author: echo
 * @Date: 2023/10/10 11:02
 * @Version: 1.0.0
 */
@Slf4j
public class SmUtils {
    // 添加 Bouncy Castle 提供者
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    /**
     * 以下为SM2推荐曲线参数
     */
    public static final SM2P256V1Curve CURVE = new SM2P256V1Curve();
    public static final BigInteger SM2_ECC_P = CURVE.getQ();
    public static final BigInteger SM2_ECC_A = CURVE.getA().toBigInteger();
    public static final BigInteger SM2_ECC_B = CURVE.getB().toBigInteger();
    public static final BigInteger SM2_ECC_N = CURVE.getOrder();
    public static final BigInteger SM2_ECC_H = CURVE.getCofactor();
    public static final BigInteger SM2_ECC_GX = new BigInteger(
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);
    public static final BigInteger SM2_ECC_GY = new BigInteger(
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);
    public static final org.bouncycastle.math.ec.ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY);
    public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT,
            SM2_ECC_N, SM2_ECC_H);

    public static final EllipticCurve JDK_CURVE = new EllipticCurve(new ECFieldFp(SM2_ECC_P), SM2_ECC_A, SM2_ECC_B);
    public static final java.security.spec.ECPoint JDK_G_POINT = new java.security.spec.ECPoint(
            G_POINT.getAffineXCoord().toBigInteger(), G_POINT.getAffineYCoord().toBigInteger());
    public static final java.security.spec.ECParameterSpec JDK_EC_SPEC = new java.security.spec.ECParameterSpec(
            JDK_CURVE, JDK_G_POINT, SM2_ECC_N, SM2_ECC_H.intValue());
    public static final String SM3_SM2 = "SM3withSM2";
    private static String encoding = "GBK";
    private static final String BC = "BC";

    /**
     * 字符串转PublicKey
     * @param publicString
     * @return
     */
    public static BCECPublicKey stringToPublic(String publicString) {
        try {
            String publicKeyHex = ByteUtils.toHexString(Base64.decode(publicString.getBytes(StandardCharsets.UTF_8)));
            BouncyCastleProvider provider = new BouncyCastleProvider();
            // 椭圆曲线参数规格
            ECParameterSpec ecParameterSpec = new ECParameterSpec(CURVE, G_POINT,
                    SM2_ECC_N, SM2_ECC_H);
            // 将私钥HEX字符串转换为X值
            BigInteger bigInteger = new BigInteger(publicKeyHex, 16);
            // 将公钥HEX字符串转换为椭圆曲线对应的点
            ECPoint ecPoint = CURVE.decodePoint(bigInteger.toByteArray());
            // 获取椭圆曲线KEY生成器
            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
            // 将椭圆曲线点转为公钥KEY对象
            return (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException("字符串转公钥失败");
        }
    }

    /**
     * 字符串转PrivateKey
     * @param privateString
     * @return
     */
    public static BCECPrivateKey stringToPrivate(String privateString) {
        try {
            String privateHex = ByteUtils.toHexString(Base64.decode(privateString.getBytes(StandardCharsets.UTF_8)));
            BouncyCastleProvider provider = new BouncyCastleProvider();
            BigInteger bigInteger = new BigInteger(privateHex, 16);
            // 将X值转为私钥KEY对象
            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
            return (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, new ECParameterSpec(CURVE, G_POINT, SM2_ECC_N)));
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException("字符串转私钥失败");
        }
    }

    private static String encrypt(String data, String publicKeyString) {
        BCECPublicKey bcecPublicKey = stringToPublic(publicKeyString);
        ECPublicKeyParameters pubKeyParameters = convertPublicKeyToParameters(bcecPublicKey);
        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        ParametersWithRandom pwr = new ParametersWithRandom(pubKeyParameters, new SecureRandom());

        engine.init(true, pwr);
        try {
            return Base64.encode(engine.processBlock(data.getBytes(), 0, data.getBytes().length));
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException("加密失败");
        }
    }

    private static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) {
        ECParameterSpec parameterSpec = ecPubKey.getParameters();
        ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),
                parameterSpec.getN(), parameterSpec.getH());
        return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters);
    }

    private static String signSm3WithSm2(String privateKeyString, String data) {
        try {
            PrivateKey privateKey = stringToPrivate(privateKeyString);
            Signature signature = Signature.getInstance(SM3_SM2, BC);
            signature.initSign(privateKey);
            signature.update(data.getBytes(encoding));
            byte signed[] = signature.sign();
            byte sign_asc[] = new byte[signed.length * 2];
            hex2Ascii(signed.length, signed, sign_asc);
            return new String(sign_asc);
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException("加签失败");
        }
    }

    public static boolean verifySign(String publicKeyString,String signedStr,String data) throws Exception{
        BCECPublicKey bcecPublicKey = stringToPublic(publicKeyString);
        Signature signature = Signature.getInstance(SM3_SM2, BC);
        signature.initVerify(bcecPublicKey);
        byte signedData[] = new byte[signedStr.length() / 2];
        ascii2Hex(signedStr.length(), signedStr.getBytes(encoding), signedData);
        signature.update(data.getBytes(encoding));
        return signature.verify(signedData);
    }

    public static String decrypt(String encryptData, String privateString) {
        BCECPrivateKey privateKey = stringToPrivate(privateString);
        byte[] decode = Base64.decode(encryptData.getBytes());
        ECPrivateKeyParameters priKeyParameters = convertPrivateKeyToParameters(privateKey);
        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        engine.init(false, priKeyParameters);
        try {
            return new String(engine.processBlock(decode, 0, decode.length));
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException("解密失败");
        }
    }

    private static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) {
        ECParameterSpec parameterSpec = ecPriKey.getParameters();
        ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),
                parameterSpec.getN(), parameterSpec.getH());
        return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters);
    }



    /**
     * 将十六进制数据转换成ASCII字符串
     *
     * @param len      十六进制数据长度
     * @param data_in  待转换的十六进制数据
     * @param data_out 已转换的ASCII字符串
     */
    private static void hex2Ascii(int len, byte data_in[], byte data_out[]) {
        byte temp1[] = new byte[1];
        byte temp2[] = new byte[1];
        for (int i = 0, j = 0; i < len; i++) {
            temp1[0] = data_in[i];
            temp1[0] = (byte) (temp1[0] >>> 4);
            temp1[0] = (byte) (temp1[0] & 0x0f);
            temp2[0] = data_in[i];
            temp2[0] = (byte) (temp2[0] & 0x0f);
            if (temp1[0] >= 0x00 && temp1[0] <= 0x09) {
                (data_out[j]) = (byte) (temp1[0] + '0');
            } else if (temp1[0] >= 0x0a && temp1[0] <= 0x0f) {
                (data_out[j]) = (byte) (temp1[0] + 0x57);
            }
            if (temp2[0] >= 0x00 && temp2[0] <= 0x09) {
                (data_out[j + 1]) = (byte) (temp2[0] + '0');
            } else if (temp2[0] >= 0x0a && temp2[0] <= 0x0f) {
                (data_out[j + 1]) = (byte) (temp2[0] + 0x57);
            }
            j += 2;
        }
    }

    /**
     * 将ASCII字符串转换成十六进制数据
     *
     * @param len      ASCII字符串长度
     * @param data_in  待转换的ASCII字符串
     * @param data_out 已转换的十六进制数据
     */
    private static void ascii2Hex(int len, byte data_in[], byte data_out[]) {
        byte[] temp1 = new byte[1];
        byte[] temp2 = new byte[1];
        for (int i = 0, j = 0; i < len; j++) {
            temp1[0] = data_in[i];
            temp2[0] = data_in[i + 1];
            if (temp1[0] >= '0' && temp1[0] <= '9') {
                temp1[0] -= '0';
                temp1[0] = (byte) (temp1[0] << 4);
                temp1[0] = (byte) (temp1[0] & 0xf0);
            } else if (temp1[0] >= 'a' && temp1[0] <= 'f') {
                temp1[0] -= 0x57;
                temp1[0] = (byte) (temp1[0] << 4);
                temp1[0] = (byte) (temp1[0] & 0xf0);
            }
            if (temp2[0] >= '0' && temp2[0] <= '9') {
                temp2[0] -= '0';
                temp2[0] = (byte) (temp2[0] & 0x0f);
            } else if (temp2[0] >= 'a' && temp2[0] <= 'f') {
                temp2[0] -= 0x57;
                temp2[0] = (byte) (temp2[0] & 0x0f);
            }
            data_out[j] = (byte) (temp1[0] | temp2[0]);
            i += 2;
        }
    }

    public static void main(String[] args) throws Exception {
        String publicKeyString = "BM6zmWApBExWzuVezdk3QwdE8PTzUBW/6JadWgAbq0XYNzcQcefZmknBZW0Cvo5GvMjDJeOUYYKuyzELNOCNfPQ=";
        String privateKeyString = "AKELqaUjpIrFu3S5xRhWZ1BIXnSosZQ+vKCjzQ47pJJT";

        String dataStr = "张晓慧";
        // 加密
        String encrypt = encrypt(dataStr, publicKeyString);
        System.out.println("加密后数据:"+encrypt);
        String decrypt = decrypt(encrypt, privateKeyString);
        System.out.println("机密后数据:"+decrypt);
        // 加签
        String sign = signSm3WithSm2(privateKeyString, encrypt);
        System.out.println("加密后数据加签:"+sign);
        // 验签
        boolean verifySign = verifySign(publicKeyString, sign, encrypt);
        System.out.println("是否验签成功:"+verifySign);
        
        // 打印数据
//        加密后数据:BLmEbT49DDfVT5IHvRcP+4yTGfLSfSbSo1U0hgUuKLWKYS6zkpIvaAurNSNG9KrfqXZInZJDUqw6W2jN82nJwcPbzECtaBmkgvXjaPRq5pG/kjBqfonSEF+hU7CUuRq0RdB39aP1Srl82g==
//                机密后数据:张晓慧
//        加密后数据加签:304502207c01cc3feef31f4a8b0ea1c5b9f45464e6ab6cd02dae6225f9d4c9ec0a4ddffc022100df39ee367d893d774f8529412698fd60c13bb1f5d97f85dbf62122a9a1d87f50
//        是否验签成功:true
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269

参考文档:https://blog.csdn.net/rtthreadiotos/article/details/121033533

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/259668
推荐阅读
相关标签
  

闽ICP备14008679号