加密方法 国密SM2、 RSA(集成Redis)、 BCrypt加密

国密SM2的用法:

  引入依赖

pom.xml
        <!-- 国密SM2 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>

  SM2工具类

SM2Util
 package com.zxd.SM2;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  14:58
 * @Description: SM2加解密、签名验签工具类
 */

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Base64;

import java.math.BigInteger;
import java.security.*;

public class SM2Util {

    // 初始化BouncyCastleProvider
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    // 获取SM2曲线参数
    private static final X9ECParameters CURVE = GMNamedCurves.getByName("sm2p256v1");
    // 定义ECDomainParameters对象
    private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE.getCurve(), CURVE.getG(), CURVE.getN());

    /**
     * 生成SM2密钥对
     *
     * @return AsymmetricCipherKeyPair 密钥对
     */
    public static AsymmetricCipherKeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        ECKeyGenerationParameters keyGenParam = new ECKeyGenerationParameters(DOMAIN_PARAMS, new SecureRandom());
        keyPairGenerator.init(keyGenParam);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 使用公钥加密数据
     *
     * @param data 待加密数据
     * @param publicKey 公钥参数
     * @return 加密后的字节数组
     */
    public static byte[] encrypt(byte[] data, ECPublicKeyParameters publicKey) throws Exception {
        SM2Engine engine = new SM2Engine();
        ParametersWithRandom pwr = new ParametersWithRandom(publicKey, new SecureRandom());
        engine.init(true, pwr);
        return engine.processBlock(data, 0, data.length);
    }

    /**
     * 使用私钥解密数据
     *
     * @param encryptedData 加密后的数据
     * @param privateKey 私钥参数
     * @return 解密后的字节数组
     */
    public static byte[] decrypt(byte[] encryptedData, ECPrivateKeyParameters privateKey) throws Exception {
        SM2Engine engine = new SM2Engine();
        engine.init(false, privateKey);
        return engine.processBlock(encryptedData, 0, encryptedData.length);
    }

    /**
     * 使用私钥对数据进行签名
     *
     * @param data 待签名数据
     * @param privateKey 私钥参数
     * @return 签名后的字节数组
     */
    public static byte[] sign(byte[] data, ECPrivateKeyParameters privateKey) throws Exception {
        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithID(privateKey, new byte[0]);
        signer.init(true, param);
        signer.update(data, 0, data.length);
        return signer.generateSignature();
    }

    /**
     * 使用公钥验证签名
     *
     * @param data 原始数据
     * @param signature 签名
     * @param publicKey 公钥参数
     * @return 验证结果,true表示验证通过,false表示验证失败
     */
    public static boolean verify(byte[] data, byte[] signature, ECPublicKeyParameters publicKey) throws Exception {
        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithID(publicKey, new byte[0]);
        signer.init(false, param);
        signer.update(data, 0, data.length);
        return signer.verifySignature(signature);
    }

    /**
     * 将Base64编码的公钥字符串转换为ECPublicKeyParameters对象
     *
     * @param base64PublicKey Base64编码的公钥字符串
     * @return ECPublicKeyParameters对象
     */
    public static ECPublicKeyParameters convertBase64StringToPublicKey(String base64PublicKey) throws Exception {
        byte[] pubKeyBytes = Base64.decode(base64PublicKey);
        ECPoint pubPoint = CURVE.getCurve().decodePoint(pubKeyBytes);
        return new ECPublicKeyParameters(pubPoint, DOMAIN_PARAMS);
    }

    /**
     * 将Base64编码的私钥字符串转换为ECPrivateKeyParameters对象
     *
     * @param base64PrivateKey Base64编码的私钥字符串
     * @return ECPrivateKeyParameters对象
     */
    public static ECPrivateKeyParameters convertBase64StringToPrivateKey(String base64PrivateKey) throws Exception {
        byte[] privKeyBytes = Base64.decode(base64PrivateKey);
        BigInteger privateKeyD = new BigInteger(1, privKeyBytes);
        return new ECPrivateKeyParameters(privateKeyD, DOMAIN_PARAMS);
    }

    /**
     * 将ECPublicKeyParameters对象转换为Base64编码的字符串
     *
     * @param publicKey 公钥参数
     * @return Base64编码的公钥字符串
     */
    public static String convertPublicKeyToBase64String(ECPublicKeyParameters publicKey) {
        return Base64.toBase64String(publicKey.getQ().getEncoded(true));
    }

    /**
     * 将ECPrivateKeyParameters对象转换为Base64编码的字符串
     *
     * @param privateKey 私钥参数
     * @return Base64编码的私钥字符串
     */
    public static String convertPrivateKeyToBase64String(ECPrivateKeyParameters privateKey) {
        return Base64.toBase64String(privateKey.getD().toByteArray());
    }
}

  SM2控制器

EncryptionController
package com.zxd.SM2;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  15:06
 * @Description: 加密控制器
 */

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.springframework.web.bind.annotation.*;

import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/encryption")
@Tag(name = "SM2模块")
public class EncryptionController {

    /**
     * 生成SM2密钥对
     *
     * @return 包含Base64编码的公钥和私钥字符串的Map
     */
    @GetMapping("/generateKeys")
    @Operation(summary = "生成SM2密钥对")
    public Map<String, String> generateKeys() throws Exception {
        AsymmetricCipherKeyPair keyPair = SM2Util.generateKeyPair();
        ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters) keyPair.getPrivate();
        ECPublicKeyParameters publicKey = (ECPublicKeyParameters) keyPair.getPublic();

        Map<String, String> keys = new HashMap<>();
        keys.put("publicKey", SM2Util.convertPublicKeyToBase64String(publicKey));
        keys.put("privateKey", SM2Util.convertPrivateKeyToBase64String(privateKey));
        return keys;
    }

    /**
     * 使用公钥加密数据
     *
     * @param data 待加密数据
     * @param publicKey Base64编码的公钥字符串
     * @return Base64编码的加密后字符串
     */
    @PostMapping("/encrypt")
    @Operation(summary = "使用公钥加密数据")
    public String encrypt(@RequestParam String data, @RequestParam String publicKey) throws Exception {
        ECPublicKeyParameters pubKey = SM2Util.convertBase64StringToPublicKey(publicKey);
        byte[] encryptedData = SM2Util.encrypt(data.getBytes(), pubKey);
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用私钥解密数据
     *
     * @param encryptedData Base64编码的加密后字符串
     * @param privateKey Base64编码的私钥字符串
     * @return 解密后的字符串
     */
    @PostMapping("/decrypt")
    @Operation(summary = "使用私钥解密数据")
    public String decrypt(@RequestParam String encryptedData, @RequestParam String privateKey) throws Exception {
        ECPrivateKeyParameters privKey = SM2Util.convertBase64StringToPrivateKey(privateKey);
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedData = SM2Util.decrypt(decodedData, privKey);
        return new String(decryptedData);
    }

    /**
     * 使用私钥对数据进行签名
     *
     * @param data 待签名数据
     * @param privateKey Base64编码的私钥字符串
     * @return Base64编码的签名字符串
     */
    @PostMapping("/sign")
    @Operation(summary = "使用私钥对数据进行签名")
    public String sign(@RequestParam String data, @RequestParam String privateKey) throws Exception {
        ECPrivateKeyParameters privKey = SM2Util.convertBase64StringToPrivateKey(privateKey);
        byte[] signature = SM2Util.sign(data.getBytes(), privKey);
        return Base64.getEncoder().encodeToString(signature);
    }

    /**
     * 使用公钥验证签名
     *
     * @param data 原始数据
     * @param signature Base64编码的签名字符串
     * @param publicKey Base64编码的公钥字符串
     * @return 验证结果,true表示验证通过,false表示验证失败
     */
    @PostMapping("/verify")
    @Operation(summary = "使用公钥验证签名")
    public boolean verify(@RequestParam String data, @RequestParam String signature, @RequestParam String publicKey) throws Exception {
        ECPublicKeyParameters pubKey = SM2Util.convertBase64StringToPublicKey(publicKey);
        byte[] decodedSignature = Base64.getDecoder().decode(signature);
        return SM2Util.verify(data.getBytes(), decodedSignature, pubKey);
    }
}

以上是生成秘钥和两对方法的基本使用实例

 

Rsa的用法:
后端生成秘钥对,把私钥存redis,并且把key和公钥返回给前端
前端加密之后吧密文和key传过来,后端通过key获取私钥解密

国密SM2和Rsa都属于加密传输数据  Rsa是国际广泛使用,SM2更适合中国且效率和安全性优于Rsa(Rsa字符串过长且可以被量子计算机破解)

  配置RSAUtil

RSAUtil
package com.zxd.RSA;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  10:52
 * @Description:
 */

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


public class RSAUtil {

    //签名算法名称
    private static final String RSA_KEY_ALGORITHM = "RSA";

    //标准签名算法名称
    private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static final String RSA2_SIGNATURE_ALGORITHM = "SHA256withRSA";

    //RSA密钥长度,默认密钥长度是1024,密钥长度必须是64的倍数,在512到65536位之间,不管是RSA还是RSA2长度推荐使用2048
    private static final int KEY_SIZE = 2048;

    /**
     * 生成密钥对
     *
     * @return 返回包含公私钥的map
     */
    public static Map<String, String> generateKey() {
        KeyPairGenerator keygen;
        try {
            keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("RSA初始化密钥出现错误,算法异常");
        }
        SecureRandom secrand = new SecureRandom();
        //初始化随机产生器
        secrand.setSeed("Alian".getBytes());
        //初始化密钥生成器
        keygen.initialize(KEY_SIZE, secrand);
        KeyPair keyPair = keygen.genKeyPair();
        //获取公钥并转成base64编码
        byte[] pub_key = keyPair.getPublic().getEncoded();
        String publicKeyStr = Base64.getEncoder().encodeToString(pub_key);
        //获取私钥并转成base64编码
        byte[] pri_key = keyPair.getPrivate().getEncoded();
        String privateKeyStr = Base64.getEncoder().encodeToString(pri_key);
        //创建一个Map返回结果
        Map<String, String> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKeyStr", publicKeyStr);
        keyPairMap.put("privateKeyStr", privateKeyStr);
        return keyPairMap;
    }

    /**
     * 公钥加密(用于数据加密)
     *
     * @param data         加密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return base64编码后的字符串
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用公钥初始化此Cipher对象(加密模式)
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * 私钥解密(用于数据解密)
     *
     * @param data          解密前的字符串
     * @param privateKeyStr 私钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data, String privateKeyStr) throws Exception {
        //Java原生base64解码
        byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用私钥初始化此Cipher对象(解密模式)
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        //对数据解密
        byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
        //返回字符串
        return new String(decrypt);
    }

    /**
     * 私钥加密(用于数据签名)
     *
     * @param data          加密前的字符串
     * @param privateKeyStr base64编码后的私钥
     * @return base64编码后后的字符串
     * @throws Exception
     */
    public static String encryptByPrivateKey(String data, String privateKeyStr) throws Exception {
        //Java原生base64解码
        byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用私钥初始化此Cipher对象(加密模式)
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * 公钥解密(用于数据验签)
     *
     * @param data         解密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用公钥初始化此Cipher对象(解密模式)
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        //对数据解密
        byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
        //返回字符串
        return new String(decrypt);
    }

    /**
     * RSA签名
     *
     * @param data     待签名数据
     * @param priKey   私钥
     * @param signType RSA或RSA2    默认为RSA2
     * @return 签名
     * @throws Exception
     */
    public static String sign(byte[] data, byte[] priKey, String signType) throws Exception {
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用私钥初始化签名对象Signature
        signature.initSign(privateKey);
        //将待签名的数据传送给签名对象(须在初始化之后)
        signature.update(data);
        //返回签名结果字节数组
        byte[] sign = signature.sign();
        //返回Base64编码后的字符串
        return Base64.getEncoder().encodeToString(sign);
    }

    /**
     * RSA校验数字签名
     *
     * @param data     待校验数据
     * @param sign     数字签名
     * @param pubKey   公钥
     * @param signType RSA或RSA2    默认为RSA2
     * @return boolean 校验成功返回true,失败返回false
     */
    public static boolean verify(byte[] data, byte[] sign, byte[] pubKey, String signType) throws Exception {
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用公钥初始化签名对象,用于验证签名
        signature.initVerify(publicKey);
        //更新签名内容
        signature.update(data);
        //得到验证结果
        return signature.verify(sign);
    }
}

  Rsa控制器

RSAUtilController
package com.zxd.RSA;

/**
 * @Auther: Zxd
 * @Date: 2024/07/18  14:02
 * @Description:
 */

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import java.util.Base64;
import java.util.Map;

@RestController
@RequestMapping("/rsa")
@Tag(name = "RSA模块")
public class RSAUtilController {

    /**
     * 生成RSA密钥对
     *
     * @return 包含Base64编码的公钥和私钥字符串的Map
     */
    @GetMapping("/generateKeys")
    @Operation(summary = "生成RSA密钥对")
    public Map<String, String> generateKeys() {
        return RsaUtil.generateKey();
    }

    /**
     * 使用公钥加密数据
     *
     * @param data 待加密数据
     * @param publicKey Base64编码的公钥字符串
     * @return Base64编码的加密后字符串
     */
    @PostMapping("/encryptByPublicKey")
    @Operation(summary = "使用公钥加密数据")
    public String encryptByPublicKey(@RequestParam String data, @RequestParam String publicKey) throws Exception {
        return RsaUtil.encryptByPublicKey(data, publicKey);
    }

    /**
     * 使用私钥解密数据
     *
     * @param encryptedData Base64编码的加密后字符串
     * @param privateKey Base64编码的私钥字符串
     * @return 解密后的字符串
     */
    @PostMapping("/decryptByPrivateKey")
    @Operation(summary = "使用私钥解密数据")
    public String decryptByPrivateKey(@RequestParam String encryptedData, @RequestParam String privateKey) throws Exception {
        return RsaUtil.decryptByPrivateKey(encryptedData, privateKey);
    }

    /**
     * 使用私钥加密数据
     *
     * @param data 待加密数据
     * @param privateKey Base64编码的私钥字符串
     * @return Base64编码的加密后字符串
     */
    @PostMapping("/encryptByPrivateKey")
    @Operation(summary = "使用私钥加密数据")
    public String encryptByPrivateKey(@RequestParam String data, @RequestParam String privateKey) throws Exception {
        return RsaUtil.encryptByPrivateKey(data, privateKey);
    }

    /**
     * 使用公钥解密数据
     *
     * @param encryptedData Base64编码的加密后字符串
     * @param publicKey Base64编码的公钥字符串
     * @return 解密后的字符串
     */
    @PostMapping("/decryptByPublicKey")
    @Operation(summary = "使用公钥解密数据")
    public String decryptByPublicKey(@RequestParam String encryptedData, @RequestParam String publicKey) throws Exception {
        return RsaUtil.decryptByPublicKey(encryptedData, publicKey);
    }

    /**
     * RSA签名
     *
     * @param data 待签名数据
     * @param privateKey Base64编码的私钥字符串
     * @param signType 签名类型(RSA或RSA2)       默认为RSA2
     * @return Base64编码的签名字符串
     */
    @PostMapping("/sign")
    @Operation(summary = "RSA签名")
    public String sign(@RequestParam String data, @RequestParam String privateKey, @RequestParam String signType) throws Exception {
        byte[] priKey = Base64.getDecoder().decode(privateKey);
        return RsaUtil.sign(data.getBytes(), priKey, signType);
    }

    /**
     * RSA校验数字签名
     *
     * @param data 原始数据
     * @param signature Base64编码的签名字符串
     * @param publicKey Base64编码的公钥字符串
     * @param signType 签名类型(RSA或RSA2)      默认为RSA2
     * @return 校验结果,true表示校验通过,false表示校验失败
     */
    @PostMapping("/verify")
    @Operation(summary = "RSA校验数字签名")
    public boolean verify(@RequestParam String data, @RequestParam String signature, @RequestParam String publicKey, @RequestParam String signType) throws Exception {
        byte[] pubKey = Base64.getDecoder().decode(publicKey);
        byte[] sig = Base64.getDecoder().decode(signature);
        return RsaUtil.verify(data.getBytes(), sig, pubKey, signType);
    }
}

包含了生成秘钥和三对基本的使用方法

 

Redis的配置:

  1. 引入依赖,配置pom.xml文件

pom.xml
         <!--Redis 依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

  2. yml文件:

application.yml
spring:
  data:
    redis:
      # Redis数据库索引(默认为0)
      database: 5
      host: 39.170.99.28
      port: 6379
      password: aofakeji2024

  3. 配置RedisConfig

 RedisConfig
package com.zxd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  10:47
 * @Description:
 */

@Configuration
public class RedisConfig {

    /**
     * 配置RedisTemplate,用于操作Redis数据库。
     * 通过此方法,我们可以定制RedisTemplate的行为,例如设置序列化器。
     *
     * @param redisConnectionFactory Redis连接工厂,用于创建Redis连接。
     * @return RedisTemplate实例,配置了字符串和对象的序列化方式。
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置ConnectionFactory,用于实际与Redis服务器的通信。
        template.setConnectionFactory(redisConnectionFactory);
        // 设置键的序列化方式为StringRedisSerializer,保证键的序列化一致性。
        template.setKeySerializer(new StringRedisSerializer());
        // 设置值的序列化方式为GenericJackson2JsonRedisSerializer,使用Jackson库将对象序列化为JSON格式。
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }

}

  4. 配置RedisUtil

RedisUtil
 package com.zxd.utils;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  11:27
 * @Description:
 */

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * spring redis 工具类
 *
 * @author wr
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisUtil
{
    @Autowired
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
    {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout)
    {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 获取有效时间
     *
     * @param key Redis键
     * @return 有效时间
     */
    public long getExpire(final String key)
    {
        return redisTemplate.getExpire(key);
    }

    /**
     * 判断 key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public Boolean hasKey(String key)
    {
        return redisTemplate.hasKey(key);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
        return redisTemplate.delete(key);
    }

    /**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */
    public boolean deleteObject(final Collection collection)
    {
        return redisTemplate.delete(collection) > 0;
    }

    /**
     * 缓存List数据
     *
     * @param key 缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList)
    {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public <T> List<T> getCacheList(final String key)
    {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 缓存Set
     *
     * @param key 缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
    {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext())
        {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key)
    {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
    {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key)
    {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 往Hash中存入数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @param value 值
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
    {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
     * 获取Hash中的数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public <T> T getCacheMapValue(final String key, final String hKey)
    {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }

    /**
     * 获取多个Hash中的数据
     *
     * @param key Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
    {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
     * 删除Hash中的某条数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return 是否成功
     */
    public boolean deleteCacheMapValue(final String key, final String hKey)
    {
        return redisTemplate.opsForHash().delete(key, hKey) > 0;
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(final String pattern)
    {
        return redisTemplate.keys(pattern);
    }
}

  Rsa测试类

RsaTest
package com.zxd;

import com.zxd.utils.RedisUtil;
import com.zxd.utils.RsaUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: Zxd
 * @Date: 2024/07/16  10:02
 * @Description:
 */
@SpringBootTest
public class RsaTest {

    /**
     * RSA数据加密和解密
     *
     * @throws Exception
     */

    @Autowired
    private RedisUtil redisUtil;

    // 加密
    @Test
    public void encryptAndDecrypt() throws Exception {

        // 生成密钥对
        Map<String, String> keyMap = RsaUtil.generateKey();
        String publicKeyStr = keyMap.get("publicKeyStr");
        String privateKeyStr = keyMap.get("privateKeyStr");
        System.out.println("-----------------生成的公钥和私钥------------------------------");
        System.out.println("获取到的公钥:" + publicKeyStr);
        System.out.println("获取到的私钥:" + privateKeyStr);


        // 待加密数据
        String data = "tranSeq=1920542585&amount=100&payType=wechat";
        String username = "zxd";
        System.out.println("-----------------加密和解密------------------------------");
        System.out.println("待加密的数据:" + data);

        // 将私钥存储到Redis
        redisUtil.setCacheObject(username, privateKeyStr,5L, TimeUnit.MINUTES);
        // 公钥加密
        String encrypt = RsaUtil.encryptByPublicKey(data, publicKeyStr);
        System.out.println("加密后数据:" + encrypt);
        String jiemi = jiemi(username,encrypt);
        System.out.println("解密后数据:" + jiemi);

        // 从Redis中获取私钥进行解密
        // String privateKeyFromRedis = redisUtil.getCacheObject("privateKeyStr");
        // String decrypt = RsaUtil.decryptByPrivateKey(encrypt, privateKeyFromRedis);
        // System.out.println("解密后数据:" + decrypt);
    }

    // 解密
    @Test
    public String jiemi(String username,String encrypt) throws Exception {
        // 从Redis中获取私钥进行解密
        String privateKeyFromRedis = redisUtil.getCacheObject(username);
        String decrypt = RsaUtil.decryptByPrivateKey(encrypt, privateKeyFromRedis);
        // System.out.println("解密后数据:" + decrypt);
        return decrypt;
    }


    /**
     * RSA数据签名和验签
     *
     * @throws Exception
     */
    @Test
    public void signAndVerify() throws Exception {
        Map<String, String> keyMap = RsaUtil.generateKey();
        String publicKeyStr = keyMap.get("publicKeyStr");
        String privateKeyStr = keyMap.get("privateKeyStr");
        System.out.println("-----------------生成的公钥和私钥------------------------------");
        System.out.println("获取到的公钥:" + publicKeyStr);
        System.out.println("获取到的私钥:" + privateKeyStr);
        // 数字签名
        String data = "tranSeq=1920542585&amount=100&payType=wechat";
        String username = "zxd";
        System.out.println("待签名的数据:" + data);
        String sign = RsaUtil.sign(data.getBytes(), Base64.getDecoder().decode(privateKeyStr), "RSA");
        // 将公钥存储到Redis
        redisUtil.setCacheObject(username, publicKeyStr,5L, TimeUnit.MINUTES);
        System.out.println("数字签名结果:" + sign);

        boolean verify = RsaUtil.verify(data.getBytes(), Base64.getDecoder().decode(sign), Base64.getDecoder().decode(publicKeyStr), "RSA");
        System.out.println("数字签名验证结果:" + verify);
    }



}

 

BCrypt加密  (通过Sa-token集成,也可通过其他方式)

  1. 引入Sa-token依赖

        <!--sa-token依赖-->
        <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot3-starter</artifactId>
            <version>1.37.0</version>
        </dependency>
BCryptTest
 package com.zxd;

import cn.dev33.satoken.secure.BCrypt;
import org.junit.jupiter.api.Test;

/**
 * @Auther: Zxd
 * @Date: 2024/07/29  16:02
 * @Description:
 */

public class BCryptTest {

    @Test
    public void bcrypt() {
        // 定义明文密码
        String password = "123456";

        // 使用BCrypt算法加密密码
        String hashpw = BCrypt.hashpw(password, BCrypt.gensalt());
        // 输出加密后的密码
        System.out.println("加密后的密码:" + hashpw);
        // 验证明文密码和加密后的密码是否匹配
        boolean checkpw = BCrypt.checkpw(password, hashpw);
        // 输出验证结果
        System.out.println("密码验证结果:" + checkpw);

        // 生成一个强度为10的盐
        String strong_salt = BCrypt.gensalt(10);
        System.out.println("强度为10的盐值:" + strong_salt);
        // 使用强度为10的盐值加密密码
        String strong_hashpw = BCrypt.hashpw(password, strong_salt);
        System.out.println("使用强度为10的盐值加密后的密码:" + strong_hashpw);
        // 验证使用强度为10的盐值加密后的密码
        boolean strong_checkpw = BCrypt.checkpw(password, strong_hashpw);
        System.out.println("使用强度为10的盐值密码验证结果:" + strong_checkpw);

        // 生成一个强度为12的盐
        String stronger_salt = BCrypt.gensalt(12);
        System.out.println("强度为12的盐值:" + stronger_salt);
        // 使用强度为12的盐值加密密码
        String stronger_hashpw = BCrypt.hashpw(password, stronger_salt);
        System.out.println("使用强度为12的盐值加密后的密码:" + stronger_hashpw);
        // 验证使用强度为12的盐值加密后的密码
        boolean stronger_checkpw = BCrypt.checkpw(password, stronger_hashpw);
        System.out.println("使用强度为12的盐值密码验证结果:" + stronger_checkpw);

        // 盐的强度越高,加密的复杂度也越高,从而提供更好的安全性
    }
}

 

posted @ 2024-07-16 14:48  xd99  阅读(118)  评论(0编辑  收藏  举报