package com.ruoyi.common.utils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.bouncycastle.util.encoders.Hex; import org.springframework.util.Base64Utils; 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.regex.Matcher; import java.util.regex.Pattern; public class SM4Utils { 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 Pattern p = Pattern.compile("\\s*|\t|\r|\n"); /** * 自动生成密钥 * * @return * @explain */ public static String generateKey() { try { return new String(Hex.encode(generateKey(DEFAULT_KEY_SIZE))); } catch (Exception e) { e.printStackTrace(); } return null; } /** * @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 待加密字符串 * @explain 加密模式:ECB * 密文长度不固定,会随着被加密字符串长度的变化而变化 */ public static String encryptEcb(String hexKey, String paramStr) { return encryptEcb(hexKey, paramStr, true); } /** * sm4加密 * * @param hexKey 16进制密钥(忽略大小写) * @param paramStr 待加密字符串 * @param isHex 是否返回16进制的加密字符串 * @return 返回16进制的加密字符串或base64String * @explain 加密模式:ECB * 密文长度不固定,会随着被加密字符串长度的变化而变化 */ public static String encryptEcb(String hexKey, String paramStr, boolean isHex) { 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 if (isHex) { cipherText = ByteUtils.toHexString(cipherArray); } else { // byte[]--> base64String cipherText = Base64Utils.encodeToString(cipherArray); if (cipherText != null && cipherText.trim().length() > 0) { Matcher m = p.matcher(cipherText); cipherText = m.replaceAll(""); } } 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) { return decryptEcb(hexKey, cipherText, true); } /** * sm4解密 * * @param hexKey 16进制密钥 * @param cipherText 16进制的加密字符串(忽略大小写) * @return 解密后的字符串 * @throws Exception * @explain 解密模式:采用ECB */ public static String decryptEcb(String hexKey, String cipherText, boolean isHex) { // 用于接收解密后的字符串 String decryptStr = ""; // hexString-->byte[] byte[] keyData = ByteUtils.fromHexString(hexKey); byte[] cipherData; if (isHex) { // hexString --> byte[] cipherData = ByteUtils.fromHexString(cipherText); } else { // base64String --> byte[] cipherData = Base64Utils.decodeFromString(cipherText); } try { // 解密 byte[] 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); } public static void main(String[] args) { //加密 // System.out.println(encryptEcb("06e6af183547026dd66eae8c0827acc7","a3b129c34a0b06800c7506075ebee2af")); //解密 System.out.println(decryptEcb("8c10e08760bb0f8465c8e8390c8c4670","fd24f99e4007788b0ea7a003ab96f7bcd0b677a5925ba1b111cadda9c108665d8d5788bac31694a2d5f83d629c74a4addde17d2fb32a5e4fa5068d857fec04c675de24b58d84de6331eebd6c191f5a4b0bddc30b0fe2462b8911c54d6149a1991509bdbb7de00257b753cd165e90e1b5cfaa1cf994e01d21df3725599c058ccf29ea5c6cc06ce2b91828c890bb164d61bc706a5093a814173605c0b36536d77a425f178f84e95d4058ca28811c7ddecce3515327555ff536579832e3ed0a26adabbf2ac22e443c12579d8d9bf066faf8db8d26ec316378dd12e97f7bdea0c51cdfb5c8f4ad199c4db29623bca807d9a26ec4fd1e59b562b588b8923253608eaa7c5d1ba4e47cf8d6eece514836cf8d18991157befab3df18bd8d38a5e1e208118977454f41f5327e02aad1d18203a1e0e71b7fc75510f532879ad037ff299a756ac1d665773ffd12e362825c45c4fd395e51a8f2a0cd94a2a671d09ef49f3e4845b58fd9959172460bb446c7911677a74e60259c6b1df5f9ddabc7da365b7ed285150de1f4ca551f43535deff943e9c63ec979bda9a7bb402f8f654cd5bf3b327a7671331e112d02fa6ad552391a032a53c512d469d13a07ae83e5c458caecad32587ebb06171b1db299e80b3bd2416c03579e679f5f0254900f97d216b296faa5fdd5d5b00d6da52bcd327cb66656c5dd659c6bd343070399fa8653e72734ce6cedba70c68c189f6a58258816c2c02ba5b368c5c2ed00c25ebd7a8e71534a4bfad9c06586c0111cfa9445345dce93330b53f6af32931ae3a8b6b2821dc8623846fda300eeb69484340c958e588521a903ff1ec2beb14d9d6c78506ff79957722a191406ea6345252e7dec630cb46869d4cb3160db78fbac93927598649de7ecf386138864cef931d56d1013936a922c46c3ed5d924a37e79142d5514fa46e48e0a38e1575c55d2d1053fe7cea649bc005ee49584d2f42a7525285ada0dbcbcfeab4c09efe2cf981f56ec18816d5cd5f90098bbba2257d8353922c4b2f009762f144031ebd0e5c6d7ce9437a4bde7f6e4972494242f69896947baf49ee71a50f2cfec157d9d5c5106e3a659153401d2df2d2f09e07fc62505e9995e6a3f206a0fd0fac830e76598bcae22d409dcf1ddcd134e0c3bb2db4d1bcb5fd4b65d55a9f268859aa16207ed998cc0ddf6cb840b38454aec10e5770e7150f0ce97db9bce166eefe096f26110ee71aa27cdbca6e42c3cd1a05179e5aa31af8f9ec6e54de3f4e51e739a66376025615c55b1eafaecade0333abe0397ffaa75d72a82c6d75df305c3d1b3d30c29058585dc4f1675c5afb1f9982c9c6f4caa6cc2ce90e57df8d0c26cb5c8e8e839f6361208fc8038882ed2914857585e76a72cde36ad6d144395eac688fb5fa8d46338df9639fb8bf86e20b39054a94981306408326161382d14e5bae5d641c44883cf13f22d9ccf1f0c06577c383f8dd230208a2920f59fe926f694a3790c62d647f4b4a0f609962a5caa015661549f2a6b4a9ed1d3ad0f5dd3a7877ce78f1d85ae4d97ca2e153e13d443cc4c5a06b6111ff989b25dea29eb85093623507f342c89d212aa72c4e5839fdfde5c5d905299c8ade53b816e382cb73aceec12af81154d64ca0cbcc3c98c317395dd726aafa975e69e700106a1b42b20f7ea77fb881980d19f6b2bee678e551736d1667726420f89fa5a3e3d28ee29414e3b25b83011b127928dc4ba49e003da2e2e5b4f8c01d002d229f48d309bda4b53ec8c0ae155df5f91c11ad3a3a2c6a0217f9a47feef49411fcbd0228e5593d60185701e0c377e5c47958d52b0f706b9be26998bffae5199cda51af5ad7fa79bf46dcd8fbb1f135827f791b547d870014ca69f5bfb5b0a73180d75c6d9f13603e4506a174a8607fe85477760c904099d7d4696716aa9bb1c8744a18fb1ae37210349a811423b1165afc28b500d1095e16a1594364c012f5f6cc3bd9f64a64187b01bcda4875ae7646540548a465c2b56caf38d98ce6a5d0f75b3c074fb2248e01cae9eb3e78dbc01302054c738d0be6a7ed37761b337c0343b453e06c9700dee8fc00a705e4a747e1a5d46588c8bace9c68eb3832f0600e46f54e85a4a3a44ea0c29c69b5c5d6b6491f0a3f0bdbd123bafe3f3dd987fcc52e30c5c6cf1e9f02f998ea2791dc72cc75dac6033198c38cec44671465120ec946145b7171a63234b531e54253f92ed2c115cfe700d35e103741744d5c29f5e466109e7aba25fb9bcc38c472ae17108e3027b68d97b8d1d90c880d92a919cbce9881d6905a33f6ce5421c570a57f056ba70966e6472f49cd3d4f48c3261e0b7ae75cb34394d692ff2b80e0d596123811bbabccf90991b5b2dc17623a0f547478fef1a1cc2df258785141e7153030d8afb58c1e214632124436cbab0c21996b5dc27704635a4b27531cfddeeadcf90fd57c681bc2b0527ffd0106692d57f36af689ea77b06bc4030fad5cdf7e60e1f03d168bd3ff798f55a629f65b8fe731fc872ad44f58176d46442e5e3afcdb69302ad58802b5ed684d3e6365a77d7e931fc691b6e7d6c63897ba5c70e6e94eb7db177a19e6d97905769fd2a40ce8ef94dc14eeced2b8dc90dd423b8255f5e926662387a52c628af72e760b94a55ea5eccc41865c503e738047d6351a4ab17b2d5139a29c830f37ba364830ecd5c47d987ae1be041b7ad0d29fa769e78266b51f49fe738d132ec7bd9c005be3b8caae434d11078cb9483ede152664954dedf3ca5aa508fdc4ab00120bfac8191851cf335a6197fb33b0dd17de0abfb2a045cf85f4a0dfcfb10846b1c2e10cb776727e27c5987a86fd8396b807c7a50b0a7a5e83cb64187da3804e24c180b16c4da848ca211a88e869b4caa5f8a486b4c41ff119497f0ac1942274c2d9817c91bb03498bc90306716a254b4e13c8327270511d71b5dfa9a44fda1f979e9d8dc8d3cb0ac5df4f5fe4940936d8e665c5667d397b9c73e13fdf79e99d8484cb940dc2451ca0a3b5cff3eebe53f7ea3d6c97a1eb1959fde7353a9d5e27c7ec4f38dcc42e8319cf150d300a0209f5de6a9d2d43450e568d236715455e2632face4c24accb6c3a33d4a6ae4f014a78866195306cc55e817836393641f6f49c05f50e3862222b0ca344ab1059e8be26937066be9e5ed12445cab67dc2de15fa26c65eaa0b0933c22c2081accc692e4a0ce463b3609038d0dea1360181f3382f00b30e61e908b8bbd5acb7b65660a97a1c4d4ba7ccce2da3095a5d8d181abc916fd831f18478db3f1590681afb55f62273d670130fa2a195d7e2a4365de887a265513df5e49e31b51ddb54807f821fdedd7eea0779dfdfcf3e64299046d6e62cc3b34d4a826f813f627bbed52964f449fe4a714ed9be8b60f54073654d749642c069780f06a34d56f5f12c29516901382568a6d3493947b046f05bcfe03ef95666e8e6d760d88f57ccf50349af4fb0e7efe2b08c94937313750dfb84d32a08b20599c3ee12a8cd6b1496cb1a069e98797a8f789743172732e35090009cffd1686809c199ef527a89d8ebbd05dfef79c6a9a958acd89aa3ed9aa648627fe62cb760c9f10e6986b0069973bf7afa4d138b56464e7f69824d852accec36dd384083215aedd55f37fc79940a0a8832397ac5e3336a436324789247c51c3e948bdcf6fb3396fe75aa8dae4f29c58cf835dc6ff2b3c4d6c236f3ce8064c8bc7a8536118a36414c842fc1a8ab6e71242ecb655df0092dee733b137feaff4b6bfc47558cbd04b3684f7f8dd31a72fcfb104f3c9568edb9da4f0826512b65b87357f45e6b7d9813b3cb03b1c3f2e1363746925e27c26e8ad0c921803c1cdf7210665971afbd8d81eda9216a25ab8ff5bb224e8f6c759e46f7254e5716db943b782a9d16451e4de2e86d3b4444b8c060aedb32d630865badb0b96a1501aac1a6f67bd74cd0b0999b0ab8173df3ad1cf6845d13e68f09853f1b57b51381f85a792afa61e2d21bac341f78cfbfa52ccf586b0572d6dff5a91e57b81186fdc52c522ff72811fe1c5d52bdee4ce6ea290f0eff38820fa8eba22117ef88797aeeeaabc66ac1ae1ec674e75c7162e10304783f2ad497361f39078d92ab21ee7d26e24fb10466665c8cc4554c11984e584b8fccaa1a19fa60db2bb6fc96d5e518a8c1ab9a8223fa4a790e15443d82d88b78deb561c423f995bd46c0cf356993227f6e90cd4311fe8624ada05ecf9a1f9d0ba9c1935c84a8763f0069e6956c75a20f2a70a84b7e25133a2e35ffa81ea74978e03881c0fceff4f2fb8a757ee4e3ff752007decda9a91b2522b0a54f8369ac878fba41ecc93396008c0d45ac019dcde8b3fa001583c740a507af08818465bedc7b103a4a8884d8fbf653f4e7a0c6b28fbe3507c7fe680429cb15def6e817c2e184fc32ff5f97a931a3f873ccce5f55b727eb270e18f343639102b5dabad5b727b7c76d80e6f61fa9b97b52c61fc703f8c8abbdf5355aaf72f22858a102ffee2fd147dd00d53141b734ee03ed9b587572f89dc2e251d207781b78e92a370cc456b3f297ea63155d530962c2159d23ea02735e5fdacecdae91888196f30c1bef6ab4643344f632e8778d6b2d102d69207f65c20e8976ba230a4c8e2c18e60d900352748570e9198d7b836cfb7f81b4d83bc52a9f6d146cc9f50c4f0d920c5b85ef51c6444fcb8b9c3e42862c345ea9ddd6b33370d36ed2779b6ca46072806e24799758b01eb7ac6570589f79b382825d4fb6ef5f02a58c6b2431c466723ee41a78f12fbfdbb2cf51514627284683f1808541cfee130aa4df80c89bd6cb92f7525a786bcd527decf10025e46291bac454a2ecab6423d9ec9327a0965abccafe69e02c83cf7faddaf6c2aa80e23261ca2174b28e36d4c46d71e68f03b4a52d8e010f36a1b12f51254c0c0b6d3ae749dc4dc292f4941353a664fafb8b2ef40d14cc3f30ba3e33b6478330e5070d3b5193c4e8dca4db9f9b2b126866ff75f11e84b98b7a7abcafa65366957e968e520317bbd42cef26008074a1ca4773e38a0e24aa4e89d74778afe2711ce979f20e8a1673b42f987dae34979fa4c832af2134f0cc625d03b77392975c344c7cb028edf407b3d987aabcd8386c29420564dff494bb4ddbbb221de3b04d01be347ac64e237a946f1bc27c264cd8d0d5f090f4bf01baf7fd652ea0eb4ab3707fe50dadb68fc78e3f4b2ee86fa39349a7bfeb6c68ed5082d9848efd93b36b6147ba5c6135d58925491f5b4119e94337ba8c5f78482d777fcc8b41059a30b956f2279c8e7e573fd220ce8f890635282093c0aea98fa8db8c29c229672d8ea3706d6757870ab6db03e881e48427c929b7478c345121289c05e43ec7bf6e1eda28")); // System.out.println(generateKey()); } }