Java实现Sm4加密和解密

/**
 * 国密SM4分组密码算法工具类(对称加密)
 * <p>GB/T 32907-2016 信息安全技术 SM4分组密码算法</p>
 * <p>SM4-ECB-PKCS5Padding</p>
 */
public class Sm4Util {

  private static final String ALGORITHM_NAME = "SM4";
  private static final String ALGORITHM_ECB_PKCS5PADDING = "SM4/ECB/PKCS5Padding";
  private static final String SM4_KEY = "55934cbe51bdafedd33dc53740607347";
  
  /**
   * SM4算法目前只支持128位(即密钥16字节)
   */
  private static final int DEFAULT_KEY_SIZE = 128;

  static {
    // 防止内存中出现多次BouncyCastleProvider的实例
    if (null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)) {
      Security.addProvider(new BouncyCastleProvider());
    }
  }

  private Sm4Util() {
  }

  /**
   * 生成密钥
   * <p>建议使用DigestUtil.binToHex将二进制转成HEX</p>
   *
   * @return 密钥16位
   * @throws Exception 生成密钥异常
   */
  public static byte[] generateKey() throws Exception {
    KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
    kg.init(DEFAULT_KEY_SIZE, new SecureRandom());
    return kg.generateKey().getEncoded();
  }

  /**
   * 加密,SM4-ECB-PKCS5Padding
   *
   * @param data 要加密的明文
   * @return 加密后的密文
   * @throws Exception 加密异常
   */
  public static byte[] encrypt(byte[] data) throws Exception {
    return sm4(data, StrUtil.hexToBin(SM4_KEY), Cipher.ENCRYPT_MODE);
  }

  /**
   * 解密,SM4-ECB-PKCS5Padding
   *
   * @param data 要解密的密文
   * @return 解密后的明文
   * @throws Exception 解密异常
   */
  public static byte[] decrypt(byte[] data) throws Exception {
    return sm4(data, StrUtil.hexToBin(SM4_KEY), Cipher.DECRYPT_MODE);
  }

  /**
   * SM4对称加解密
   *
   * @param input 明文(加密模式)或密文(解密模式)
   * @param key   密钥
   * @param mode  Cipher.ENCRYPT_MODE - 加密;Cipher.DECRYPT_MODE - 解密
   * @return 密文(加密模式)或明文(解密模式)
   * @throws Exception 加解密异常
   */
  private static byte[] sm4(byte[] input, byte[] key, int mode)
      throws Exception {
    SecretKeySpec sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
    Cipher cipher = Cipher
        .getInstance(ALGORITHM_ECB_PKCS5PADDING, BouncyCastleProvider.PROVIDER_NAME);
    cipher.init(mode, sm4Key);
    return cipher.doFinal(input);
  }
}


/**
 * 字符串工具类
 *
 */
public class StrUtil {

  /**
   * 字节数组转十六进制字符串
   *
   * @param bytes 字节数组
   * @return 十六进制字符串
   */
  public static String binToHex(byte[] bytes) {
    return Hex.toHexString(bytes).toUpperCase();
  }

  /**
   * 十六进制字符串转字节数组
   *
   * @param hex 字节数组
   * @return 十六进制字符串
   */
  public static byte[] hexToBin(String hex) {
    return Hex.decode(hex);
  }

  /**
   * 字节数组转UTF8字符串
   *
   * @param bytes 字节数组
   * @return UTF8字符串
   */
  public static String binToStr(byte[] bytes) {
    return new String(bytes, StandardCharsets.UTF_8);
  }

  /**
   * UTF8字符串转字节数组
   *
   * @param str UTF8字符串
   * @return 字节数组
   */
  public static byte[] strToBin(String str) {
    return Strings.toUTF8ByteArray(str);
  }
}

示例代码        

        JavaUtilsDemo: java工具类实例代码

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值