Java Sm4+Base64加密传输

一、使用Sm4首先需要建立一个工具类

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.sansan.host_fix_admin.config.AppConfig;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;

public class Sm4Util {

  static {
    Security.addProvider(new BouncyCastleProvider());
  }

  private static final String ENCODING = "UTF-8";
  public static final String ALGORITHM_NAME = "SM4";
  // 加密算法/分组加密模式/分组填充方式
  // PKCS5Padding-以8个字节为一组进行分组加密
  // 定义分组加密模式使用:PKCS5Padding
  public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
  // 128-32位16进制;256-64位16进制
  public static final int DEFAULT_KEY_SIZE = 128;

  /**
   * 自动生成密钥
   *
   * @return
   * @explain
   */
  public static String generateKey() throws Exception {
    return new String(Hex.encodeHex(generateKey(DEFAULT_KEY_SIZE), false));
  }

  /**
   * @param keySize
   * @return
   * @throws Exception
   * @explain
   */
  public static byte[] generateKey(int keySize) throws Exception {
    KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
    kg.init(keySize, new SecureRandom());
    return kg.generateKey().getEncoded();
  }

  /**
   * 生成ECB暗号
   *
   * @param algorithmName 算法名称
   * @param mode          模式
   * @param key
   * @return
   * @throws Exception
   * @explain ECB模式(电子密码本模式:Electronic codebook)
   */
  private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key)
      throws Exception {
    Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
    Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
    cipher.init(mode, sm4Key);
    return cipher;
  }

  /**
   * sm4加密
   *
   * @param hexKey   16进制密钥(忽略大小写)
   * @param paramStr 待加密字符串
   * @return 返回16进制的加密字符串
   * @explain 加密模式:ECB 密文长度不固定,会随着被加密字符串长度的变化而变化
   */
  public static String encryptEcb(String hexKey, String paramStr) {
    try {
      String cipherText = "";
      // 16进制字符串-->byte[]
      byte[] keyData = ByteUtils.fromHexString(hexKey);
      // String-->byte[]
      byte[] srcData = paramStr.getBytes(ENCODING);
      // 加密后的数组
      byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
      // byte[]-->hexString
      cipherText = ByteUtils.toHexString(cipherArray);
      return cipherText;
    } catch (Exception e) {
      return paramStr;
    }
  }

  /**
   * 加密模式之Ecb
   *
   * @param key
   * @param data
   * @return
   * @throws Exception
   * @explain
   */
  public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
    Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
    return cipher.doFinal(data);
  }

  /**
   * sm4解密
   *
   * @param hexKey     16进制密钥
   * @param cipherText 16进制的加密字符串(忽略大小写)
   * @return 解密后的字符串
   * @throws Exception
   * @explain 解密模式:采用ECB
   */
  public static String decryptEcb(String hexKey, String cipherText) {
    // 用于接收解密后的字符串
    String decryptStr = "";
    // hexString-->byte[]
    byte[] keyData = ByteUtils.fromHexString(hexKey);
    // hexString-->byte[]
    byte[] cipherData = ByteUtils.fromHexString(cipherText);
    // 解密
    byte[] srcData = new byte[0];
    try {
      srcData = decrypt_Ecb_Padding(keyData, cipherData);
      // byte[]-->String
      decryptStr = new String(srcData, ENCODING);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return decryptStr;
  }

  /**
   * 解密
   *
   * @param key
   * @param cipherText
   * @return
   * @throws Exception
   * @explain
   */
  public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
    Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
    return cipher.doFinal(cipherText);
  }

  /**
   * 校验加密前后的字符串是否为同一数据
   *
   * @param hexKey     16进制密钥(忽略大小写)
   * @param cipherText 16进制加密后的字符串
   * @param paramStr   加密前的字符串
   * @return 是否为同一数据
   * @throws Exception
   * @explain
   */
  public static boolean verifyEcb(String hexKey, String cipherText, String paramStr)
      throws Exception {
    // 用于接收校验结果
    boolean flag = false;
    // hexString-->byte[]
    byte[] keyData = ByteUtils.fromHexString(hexKey);
    // 将16进制字符串转换成数组
    byte[] cipherData = ByteUtils.fromHexString(cipherText);
    // 解密
    byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);
    // 将原字符串转换成byte[]
    byte[] srcData = paramStr.getBytes(ENCODING);
    // 判断2个数组是否一致
    flag = Arrays.equals(decryptData, srcData);
    return flag;
  }

  public static void main(String[] args) {
    try {
      byte[] key = ByteUtils.fromHexString(AppConfig.sm4key);
      SymmetricCrypto sm4 = SmUtil.sm4(key);
//            String user1 = sm4.encryptBase64("user1");
//            System.out.println("user1 = " + user1);
//            String s = sm4.decryptStr(user1);
//            System.out.println("s = " + s);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

二、工具类建好之后就可以直接使用了

 

1. 在全局定义一个sm4key

2. data:代表的是你想要加密的字符串

三、Base进行加密

1.以为Base64要加密Byte,所以我们先将String转为Byte。

2.然后就可以直接初始化BASE64Encoder,进行加密

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: javasm2加密算法是一个基于椭圆曲线密码体制的非对称加密算法,它利用椭圆曲线上的点和点间的运算来实现加密和解密的过程。 具体的步骤如下: 1. 选择一个椭圆曲线参数集,包括曲线方程、椭圆曲线基点和曲线上的一个大整数N。 2. 选择一个私钥,即一个小于N的整数d作为加密方的私钥。 3. 根据私钥d计算公钥Q,即Q=d*G,其中G是椭圆曲线的基点。 4. 将待加密的明文转化为椭圆曲线上的点P,通过对明文进行哈希算法得到一个大整数H,然后将H与椭圆曲线的基点G相乘得到点P=H*G。 5. 选择一个随机数k,并计算点C1=k*G和C2=P+k*Q,其中C1和C2分别是加密后的曲线上的点。 6. 最终的密文为将C1和C2表示成字节串的形式。 对于解密过程,将C1和C2恢复成椭圆曲线上的点,即C1=k*G,C2=P+k*Q,然后通过计算C2-k*C1恢复出明文的点P,并将P转化成原始的明文。 javasm2加密算法通过利用椭圆曲线的数学性质,使得加密强度较高,同时运算速度也比较快。该算法被广泛应用于密码学领域,用于保护敏感信息的安全。 ### 回答2: JavaSM2是一种基于Java开发的SM2非对称加密算法的实现。SM2是中国自主研发的一种密码算法,其具有良好的安全性和高效性,特别适用于数字签名和密钥交换等场景。 JavaSM2的使用步骤如下: 1.生成密钥对:首先使用Java的密钥生成器生成SM2的公钥和私钥。公钥用于加密和验证数字签名,而私钥用于解密和生成数字签名。 2.加密数据:使用SM2的公钥对待加密的数据进行加密。加密后的数据只能使用相应的私钥进行解密。 3.解密数据:使用SM2的私钥对加密后的数据进行解密,得到原始数据。 4.生成数字签名:使用SM2的私钥对待签名的数据进行签名,生成数字签名。数字签名用于验证数据的完整性和真实性。 5.验证数字签名:使用SM2的公钥对数字签名进行验证,确认数据的完整性和真实性。 JavaSM2的优点是具有较高的安全性,采用SM2算法可以保证数据的机密性和完整性。此外,它还具有高效性,能够在较短的时间内完成加密、解密和签名等操作。 总体而言,JavaSM2加密是一种安全可靠的加密算法实现,适用于各种安全通信和数据传输场景。 ### 回答3: JavaSM2是一种基于国密SM2算法的加密技术。SM2算法是中国自主研发的非对称加密算法,可用于数字签名、密钥交换和加密等安全通信应用。 JavaSM2加密C意味着使用Java语言实现SM2算法对C语言代码进行加密保护。加密过程大致分为三个步骤: 1. 密钥生成:首先需要生成SM2算法所需的密钥对,包括公钥和私钥。公钥用于加密,私钥用于解密。JavaSM2通过调用相关API生成密钥对。 2. 加密处理:将要加密的C语言代码转化为字节流数据,再调用JavaSM2提供的API进行加密操作。加密后的数据将变得不可读且不易被篡改,提高代码的安全性。 3. 解密操作:将加密的数据传递给相应的解密方法,并使用私钥进行解密处理。解密后的数据将还原成原始的C语言代码,以便进行后续的使用和执行。 通过JavaSM2加密C语言代码可以提高代码的安全性,防止代码泄露和恶意篡改,保护软件的知识产权。同时也能够保护软件系统的安全,减少攻击者对系统的恶意入侵。因此,JavaSM2加密C语言代码在保障信息安全和知识产权保护方面具有重要的意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值