【工具】国密SM4算法加解密
SM4是一种分组密码算法,其分组长度为128位(即16字节,4字),密钥长度也为128位(即16字节,4字)。其加解密过程采用了32轮迭代机制(与DES、AES类似),每一轮需要一个轮密钥(与DES、AES类似)。
1.引入密码算法相关包
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.59</version> </dependency>
2.工具类
import java.nio.charset.StandardCharsets; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import org.apache.tomcat.util.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; 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; private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider(); // 自定义密钥或使用generateKey生成密钥 public static String secret_key = "fjeWEhu41223Tycd"; /** * 自动生成密钥 * @explain * @return * @throws NoSuchAlgorithmException * @throws NoSuchProviderException */ public static byte[] generateKey() throws Exception { return generateKey(DEFAULT_KEY_SIZE); } /** * @explain * @param keySize * @return * @throws Exception */ 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(); } /** * 加密 * * @param content 加密的字符串 * @param encryptKey key值 */ public static String encrypt(String content) throws Exception { //设置Cipher对象 Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret_key.getBytes(), ALGORITHM_NAME)); //调用doFinal byte[] b = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); // 转base64 return Base64.encodeBase64String(b); } /** * 解密 * * @param encryptStr 解密的字符串 * @param decryptKey 解密的key值 */ public static String decrypt(String encryptStr) throws Exception{ //base64格式的key字符串转byte byte[] decodeBase64 = Base64.decodeBase64(encryptStr); //设置Cipher对象 Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, PROVIDER); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret_key.getBytes(), ALGORITHM_NAME)); //调用doFinal解密 byte[] decryptBytes = cipher.doFinal(decodeBase64); return new String(decryptBytes); } public static void main(String[] args) { try { System.out.println(encrypt("123qwe++")); System.out.println(encrypt("rwertw")); } catch (Exception e) { e.printStackTrace(); } } }
3.出现的问题
maven打包部署没有出现问题,
但是可运维的jar包,打包后执行报错JCE cannot authenticate the provider BC,查询了问题,发现还需要配置jdk
进入jdk安装目录下jre/lib/security,编辑文件java.security
添加配置:11是序号,前面对应递增就行,如果你最后是9,这里需要改成10.
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
然后从项目maven库里拷贝使用到的 bcprov-jdk15on-1.59.jar,复制到jre/lib/ext/目录下
之后重启项目(一定不能忘记这一步)