文章目录

  • 前言
    • 1.AES
    • 2.DES
    • 3、BCrypt
    • 4、Http Basic
    • 5、MD5
    • 6、RSA
    • 7、SHA256
    • 8、SM3
    • 9、SM4

前言

JAVA能够实现各种加解密方式,这里对各种加密方式做了封装,包括AES、DES、BCrypt、MD5、SHA、RSA、SM3、SM4、Http Basic等。


1.AES

ASE为对称加密。

工具类:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;/*** <p>AES加解密工具类</p>** @author zhuquanwen* @version 1.0* @date 2018/7/13 17:31* @since jdk1.8**/
@SuppressWarnings("unused")
public final class AesUtils {private AesUtils() {}private static final String CKEY = "encryptionIntVec";/*** 密钥*/public static final String CRYPT_KEY = "10f5dd7c2d45d247";private static final String ALGORITHMSTR = "AES/CBC/PKCS5Padding";public static String doDecrypt(String source) {String target = "";try {target = aesDecrypt(source);} catch (Exception ignored) {}return StringUtils.isNotBlank(target) ? target : source;}public static String doEncrypt(String source) {String target = "";try {target = aesEncrypt(source, CRYPT_KEY);} catch (Exception ignored) {}return StringUtils.isNotBlank(target) ? target : source;}/*** aes解密** @param encrypt 内容* @return String* @throws Exception 异常*/public static String aesDecrypt(String encrypt) throws Exception {return aesDecrypt(encrypt, CRYPT_KEY);}/*** aes加密** @param content content* @return String* @throws Exception 异常*/public static String aesEncrypt(String content) throws Exception {return aesEncrypt(content, CRYPT_KEY);}/*** 将byte[]转为各种进制的字符串** @param bytes byte[]* @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制* @return 转换后的字符串*/public static String binary(byte[] bytes, int radix) {// 这里的1代表正数return new BigInteger(1, bytes).toString(radix);}/*** common 64 encode** @param bytes 待编码的byte[]* @return 编码后的base 64 code*/public static String base64Encode(byte[] bytes) {return Base64.encodeBase64String(bytes);}/*** common 64 decode** @param base64Code 待解码的base 64 code* @return 解码后的byte[]*/public static byte[] base64Decode(String base64Code) {return StringUtils.isEmpty(base64Code) ? null : java.util.Base64.getDecoder().decode(base64Code);}public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {byte[] raw = encryptKey.getBytes(StandardCharsets.UTF_8);SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance(ALGORITHMSTR);//使用CBC模式,需要一个向量iv,可以增加加密算法的强度IvParameterSpec iv = new IvParameterSpec(CKEY.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));}/*** AES加密为base 64 code** @param content    待加密的内容* @param encryptKey 加密密钥* @return 加密后的base 64 code* @throws Exception 异常*/public static String aesEncrypt(String content, String encryptKey) throws Exception {return base64Encode(aesEncryptToBytes(content, encryptKey));}public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {byte[] raw = decryptKey.getBytes(StandardCharsets.UTF_8);SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance(ALGORITHMSTR);IvParameterSpec iv = new IvParameterSpec(CKEY.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);byte[] decryptBytes = cipher.doFinal(encryptBytes);return new String(decryptBytes, StandardCharsets.UTF_8);}/*** 将base 64 code AES解密** @param encryptStr 待解密的base 64 code* @param decryptKey 解密密钥* @return 解密后的string* @throws Exception 异常*/public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);}}

单元测试:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;/*** AES加解密测试类* @author zhuquanwen**/
public class AesUtilsTests {/*** 测试AES 默认加密* */@Testpublic void aesEncrpty() throws Exception {String sec = AesUtils.aesEncrypt("USER2");System.out.println(sec);Assertions.assertNotNull(sec);}/**** 测试AES默认解密* */@Testpublic void aesDecrpty() throws Exception {String ori = AesUtils.aesDecrypt("Cg2jBQvUGJJUMfalO+HF5g==");Assertions.assertEquals("gfdx", ori);}/*** 测试AES 带KEY加密* */@Testpublic void aesEncrptyWithKey() throws Exception {String k = "6x9o67h5BO205Cfv";String sec = AesUtils.aesEncrypt("admin", k);Assertions.assertNotNull(sec);}/*** 测试AES 带KEY解密* */@Testpublic void aesDecrptyWithKey() throws Exception {String k = "6x9o67h5BO205Cfv";String ori = AesUtils.aesDecrypt("yij1zaxI6X10t7v6OpW7gw==", k);Assertions.assertEquals("admin", ori);}}

2.DES

DES为对称加密

工具类:

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 17:29*/
public class DesUtils {private DesUtils() {}/*** iv向量*/private static final String DESIV = "12345678";//    /**
//     * AlgorithmParameterSpec
//     */
//    private static AlgorithmParameterSpec IV = null;/*** SHA1PRNG*/private static final String SHA1PRNG = "SHA1PRNG";/*** 密钥*/public static final String CRYPT_KEY = "10f5dd7c2d45d247";/*** CBC加密模式*/private static final String DES_CBC_PKCS5PADDING = "DES/CBC/PKCS5Padding";/*** OFB加密模式*/private static final String DES_OFB_PKCS5PADDING = "DES/OFB/PKCS5Padding";/*** CFB加密模式*/private static final String DES_CFB_PKCS5_PADDING = "DES/CFB/PKCS5Padding";/*** ECB加密模式*/private static final String DES_ECB_PKCS5_PADDING = "DES/ECB/PKCS5Padding";/*** DES模式*/private static final String DES = "DES";/*** 加密模式*/private static final int ENCRYPT_MODE = 1;/*** 解密模式*/private static final int DECRYPT_MODE = 2;/*** 字符串des加密** @param data   需要加密的字符串* @param mode   加密模式 (ECB/CBC/OFB/CFB)* @param secret 密钥* @return 加密结果* @throws Exception 异常*/public static String encrypt(String data, Mode mode, String secret) throws Exception {Cipher cipher = getPattern(mode, ENCRYPT_MODE, secret);byte[] pasByte = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(pasByte);}/*** 字符串des加密** @param data   需要加密的字符串* @param secret 密钥* @return 加密结果* @throws Exception 异常*/public static String encrypt(String data, String secret) throws Exception {Cipher cipher = getPattern(Mode.CBC, ENCRYPT_MODE, secret);byte[] pasByte = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(pasByte);}/*** 字符串des加密** @param data 需要加密的字符串* @return 加密结果* @throws Exception 异常*/public static String encrypt(String data) throws Exception {Cipher cipher = getPattern(Mode.CBC, ENCRYPT_MODE, CRYPT_KEY);byte[] pasByte = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(pasByte);}/*** 字符串des解密** @param data 需要解密的字符串* @param mode 解密模式 (ECB/CBC/OFB/CFB)* @return 解密结果* @throws Exception 异常* @author sucb*/public static String decrypt(String data, Mode mode, String secret) throws Exception {Cipher cipher = getPattern(mode, DECRYPT_MODE, secret);byte[] pasByte = cipher.doFinal(Base64.getDecoder().decode(data));return new String(pasByte, StandardCharsets.UTF_8);}/*** 字符串des解密** @param data 需要解密的字符串* @return 解密结果* @throws Exception 异常* @author sucb*/public static String decrypt(String data, String secret) throws Exception {Cipher cipher = getPattern(Mode.CBC, DECRYPT_MODE, secret);byte[] pasByte = cipher.doFinal(Base64.getDecoder().decode(data));return new String(pasByte, StandardCharsets.UTF_8);}/*** 字符串des解密** @param data 需要解密的字符串* @return 解密结果* @throws Exception 异常* @author sucb*/public static String decrypt(String data) throws Exception {Cipher cipher = getPattern(Mode.CBC, DECRYPT_MODE, CRYPT_KEY);byte[] pasByte = cipher.doFinal(Base64.getDecoder().decode(data));return new String(pasByte, StandardCharsets.UTF_8);}/*** 文件 file 进行加密并保存目标文件 destFile 中** @param file     要加密的文件 如 c:/test/file.txt* @param destFile 加密后存放的文件名 如 c:/ 加密后文件 .txt* @param mode     加密模式 (ECB/CBC/OFB/CFB)* @return 加密结果   0:异常 1:加密成功; 5:未找到需要加密的文件*/public int encryptFile(String file, String destFile, Mode mode) throws Exception {int result = 0;try {Cipher cipher = getPattern(mode, ENCRYPT_MODE, CRYPT_KEY);InputStream is = new FileInputStream(file);OutputStream out = new FileOutputStream(destFile);CipherInputStream cis = new CipherInputStream(is, cipher);byte[] buffer = new byte[1024];int r;while ((r = cis.read(buffer)) > 0) {out.write(buffer, 0, r);}cis.close();is.close();out.close();result = 1;} catch (FileNotFoundException e) {result = 5;}return result;}/*** 文件 file 进行解密并保存目标文件 destFile 中** @param file     要解密的文件 如 c:/test/file.txt* @param destFile 解密后存放的文件名 如 c:/ 解密后文件 .txt* @param mode     解密模式 (ECB/CBC/OFB/CFB)* @return 解密结果 0:解密异常;1:解密正常;5:未找到需要解密的文件* @author sucb* @date 2017年3月2日下午7:58:56*/public int decryptFile(String file, String destFile, Mode mode) throws Exception {int result = 0;try {Cipher cipher = getPattern(mode, DECRYPT_MODE, CRYPT_KEY);InputStream is = new FileInputStream(file);OutputStream out = new FileOutputStream(destFile);CipherOutputStream cos = new CipherOutputStream(out, cipher);byte[] buffer = new byte[1024];int r;while ((r = is.read(buffer)) >= 0) {cos.write(buffer, 0, r);}cos.close();out.close();is.close();result = 1;} catch (FileNotFoundException e) {result = 5;}return result;}/*** 通过密钥获得key** @param secretKey 密钥*/public static Key getKey(String secretKey) throws NoSuchAlgorithmException {SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG);secureRandom.setSeed(secretKey.getBytes());KeyGenerator generator = KeyGenerator.getInstance("DES");generator.init(secureRandom);return generator.generateKey();}/*** 初始化cipher** @param mode       加密/解密模式 (ECB/CBC/OFB/CFB)* @param cipherMode cipher工作模式 1:加密; 2:解密* @return cipher* @throws Exception 异常*/private static Cipher getPattern(Mode mode, int cipherMode, String secret) throws Exception {AlgorithmParameterSpec IV = new IvParameterSpec(DESIV.getBytes(StandardCharsets.UTF_8));secret = secret == null ? CRYPT_KEY : secret;Key key = getKey(secret);Cipher cipher;switch (mode) {case OFB:cipher = Cipher.getInstance(DES_OFB_PKCS5PADDING);cipher.init(cipherMode, key, IV);break;case CFB:cipher = Cipher.getInstance(DES_CFB_PKCS5_PADDING);cipher.init(cipherMode, key, IV);break;case DES:cipher = Cipher.getInstance(DES);cipher.init(cipherMode, key);break;case ECB:cipher = Cipher.getInstance(DES_ECB_PKCS5_PADDING);cipher.init(cipherMode, key);break;default:cipher = Cipher.getInstance(DES_CBC_PKCS5PADDING);cipher.init(cipherMode, key, IV);break;}return cipher;}public enum Mode {/*** DES*/DES,/*** CFB*/CFB,/*** OFB*/OFB,/*** CBC,默认模式*/CBC,/*** ECB*/ECB;}}

单元测试:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 18:00*/
class DesUtilsTest {@Testpublic void test1() throws Exception {String encrypt = DesUtils.encrypt("123456");System.out.println(encrypt);Assertions.assertNotNull(encrypt);}@Testpublic void test2() throws Exception {String decrypt = DesUtils.decrypt("yGj4sGSmFxs=");System.out.println(decrypt);Assertions.assertNotNull(decrypt);}/*** DES模式* */@Testpublic void test3() throws Exception {String encrypt = DesUtils.encrypt("123456", DesUtils.Mode.DES, "abcdefgh");System.out.println(encrypt);String data = DesUtils.decrypt(encrypt, DesUtils.Mode.DES, "abcdefgh");System.out.println(data);}/*** CBC模式* */@Testpublic void test4() throws Exception {String encrypt = DesUtils.encrypt("123456", DesUtils.Mode.CBC, "abcdefgh");System.out.println(encrypt);String data = DesUtils.decrypt(encrypt, DesUtils.Mode.CBC, "abcdefgh");System.out.println(data);}/*** ECB模式* */@Testpublic void test5() throws Exception {String encrypt = DesUtils.encrypt("123456", DesUtils.Mode.ECB, "abcdefgh");System.out.println(encrypt);String data = DesUtils.decrypt(encrypt, DesUtils.Mode.ECB, "abcdefgh");System.out.println(data);}/*** CFB模式* */@Testpublic void test6() throws Exception {String encrypt = DesUtils.encrypt("123456", DesUtils.Mode.CFB, "abcdefgh");System.out.println(encrypt);String data = DesUtils.decrypt(encrypt, DesUtils.Mode.CFB, "abcdefgh");System.out.println(data);}/*** OFB模式* */@Testpublic void test7() throws Exception {String encrypt = DesUtils.encrypt("123456", DesUtils.Mode.OFB, "abcdefgh");System.out.println(encrypt);String data = DesUtils.decrypt(encrypt, DesUtils.Mode.OFB, "abcdefgh");System.out.println(data);}}

3、BCrypt

BCrpty为单向加密
工具类:

package com.iscas.common.tools.core.security;import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.regex.Pattern;/*** <p>BCrypt加解密工具类</p>* @author zhuquanwen* @version 1.0* @since jdk1.8* @date 2021/03/14 13:02**/
@SuppressWarnings({"CStyleArrayDeclaration", "unused", "AliArrayNamingShouldHaveBracket", "AlibabaLowerCamelCaseVariableNaming", "AlibabaClassNamingShouldBeCamel", "AlibabaConstantFieldShouldBeUpperCase", "RegExpSimplifiable"})
public class BCryptUtils {private static final Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;private static final int BCRYPT_SALT_LEN = 16;/**Blowfish parameters*/private static final int BLOWFISH_NUM_ROUNDS = 16;/**Initial contents of key schedule*/private static final int P_orig[] = {0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,0x9216d5d9, 0x8979fb1b};private static final int S_orig[] = {0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5,0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27,0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993,0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af,0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5,0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68,0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4,0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248,0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4,0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd,0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc,0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0,0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8,0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01,0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64,0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8,0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86,0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e,0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a,0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6,0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7,0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546,0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941,0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c,0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856,0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87,0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70,0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1,0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1,0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa,0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37,0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24,0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7,0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f,0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71,0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74,0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0,0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df,0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641,0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de,0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5,0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212,0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315,0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d,0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6,0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da,0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d,0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc,0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2,0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8,0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46,0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40,0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e,0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d,0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b,0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667,0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb,0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df,0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891,0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5,0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00,0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76,0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0,0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6};static private final int bf_crypt_ciphertext[] = {0x4f727068, 0x65616e42,0x65686f6c, 0x64657253, 0x63727944, 0x6f756274};static private final char base64_code[] = {'.', '/', 'A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U','V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j','k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y','z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};static private final byte index_64[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 54, 55,56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7,8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,-1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1};private static int P[];private static int S[];private static void init_key() {P = P_orig.clone();S = S_orig.clone();}static void encode_base64(byte d[], int len, StringBuilder rs)throws IllegalArgumentException {int off = 0;int c1, c2;if (len <= 0 || len > d.length) {throw new IllegalArgumentException("Invalid len");}while (off < len) {c1 = d[off++] & 0xff;rs.append(base64_code[(c1 >> 2) & 0x3f]);c1 = (c1 & 0x03) << 4;if (off >= len) {rs.append(base64_code[c1 & 0x3f]);break;}c2 = d[off++] & 0xff;c1 |= (c2 >> 4) & 0x0f;rs.append(base64_code[c1 & 0x3f]);c1 = (c2 & 0x0f) << 2;if (off >= len) {rs.append(base64_code[c1 & 0x3f]);break;}c2 = d[off++] & 0xff;c1 |= (c2 >> 6) & 0x03;rs.append(base64_code[c1 & 0x3f]);rs.append(base64_code[c2 & 0x3f]);}}static byte[] decode_base64(String s) throws IllegalArgumentException {ByteArrayOutputStream out = new ByteArrayOutputStream(BCryptUtils.BCRYPT_SALT_LEN);int off = 0, slen = s.length(), olen = 0;byte c1, c2, c3, c4, o;if (BCryptUtils.BCRYPT_SALT_LEN <= 0) {throw new IllegalArgumentException("Invalid maxolen");}while (off < slen - 1 && olen < BCryptUtils.BCRYPT_SALT_LEN) {c1 = char64(s.charAt(off++));c2 = char64(s.charAt(off++));if (c1 == -1 || c2 == -1) {break;}o = (byte) (c1 << 2);o |= (c2 & 0x30) >> 4;out.write(o);if (++olen >= BCryptUtils.BCRYPT_SALT_LEN || off >= slen) {break;}c3 = char64(s.charAt(off++));if (c3 == -1) {break;}o = (byte) ((c2 & 0x0f) << 4);o |= (c3 & 0x3c) >> 2;out.write(o);if (++olen >= BCryptUtils.BCRYPT_SALT_LEN || off >= slen) {break;}c4 = char64(s.charAt(off++));o = (byte) ((c3 & 0x03) << 6);o |= c4;out.write(o);++olen;}return out.toByteArray();}private static byte char64(char x) {if (x > index_64.length) {return -1;}return index_64[x];}public static String gensalt(int log_rounds, SecureRandom random) {if (log_rounds < 4 || log_rounds > 31) {throw new IllegalArgumentException("Bad number of rounds");}StringBuilder rs = new StringBuilder();byte rnd[] = new byte[BCRYPT_SALT_LEN];random.nextBytes(rnd);rs.append("$2a$");if (log_rounds < 10) {rs.append("0");}rs.append(log_rounds);rs.append("$");encode_base64(rnd, rnd.length, rs);return rs.toString();}public static String hashpw(String password, String salt) {String real_salt;byte passwordb[], saltb[], hashed[];char minor = (char) 0;int rounds, off;StringBuilder rs = new StringBuilder();int saltLength = salt.length();if (saltLength < 28) {throw new IllegalArgumentException("Invalid salt");}if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {throw new IllegalArgumentException("Invalid salt version");}if (salt.charAt(2) == '$') {off = 3;} else {minor = salt.charAt(2);if (minor != 'a' || salt.charAt(3) != '$') {throw new IllegalArgumentException("Invalid salt revision");}off = 4;}if (saltLength - off < 25) {throw new IllegalArgumentException("Invalid salt");}// Extract number of roundsif (salt.charAt(off + 2) > '$') {throw new IllegalArgumentException("Missing salt rounds");}rounds = Integer.parseInt(salt.substring(off, off + 2));real_salt = salt.substring(off + 3, off + 25);passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes(StandardCharsets.UTF_8);saltb = decode_base64(real_salt);hashed = crypt_raw(passwordb, saltb, rounds);rs.append("$2");if (minor >= 'a') {rs.append(minor);}rs.append("$");if (rounds < 10) {rs.append("0");}rs.append(rounds);rs.append("$");encode_base64(saltb, saltb.length, rs);encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);return rs.toString();}private static byte[] crypt_raw(byte password[], byte salt[], int log_rounds) {int cdata[] = bf_crypt_ciphertext.clone();int clen = cdata.length;byte ret[];long rounds = roundsForLogRounds(log_rounds);init_key();ekskey(salt, password);for (long i = 0; i < rounds; i++) {key(password);key(salt);}for (int i = 0; i < 64; i++) {for (int j = 0; j < (clen >> 1); j++) {encipher(cdata, j << 1);}}ret = new byte[clen * 4];for (int i = 0, j = 0; i < clen; i++) {ret[j++] = (byte) ((cdata[i] >> 24) & 0xff);ret[j++] = (byte) ((cdata[i] >> 16) & 0xff);ret[j++] = (byte) ((cdata[i] >> 8) & 0xff);ret[j++] = (byte) (cdata[i] & 0xff);}return ret;}static long roundsForLogRounds(int log_rounds) {if (log_rounds < 4 || log_rounds > 31) {throw new IllegalArgumentException("Bad number of rounds");}return 1L << log_rounds;}private static void ekskey(byte data[], byte key[]) {int i;int koffp[] = {0}, doffp[] = {0};int lr[] = {0, 0};int plen = P.length, slen = S.length;for (i = 0; i < plen; i++) {P[i] = P[i] ^ streamtoword(key, koffp);}for (i = 0; i < plen; i += 2) {lr[0] ^= streamtoword(data, doffp);lr[1] ^= streamtoword(data, doffp);encipher(lr, 0);P[i] = lr[0];P[i + 1] = lr[1];}for (i = 0; i < slen; i += 2) {lr[0] ^= streamtoword(data, doffp);lr[1] ^= streamtoword(data, doffp);encipher(lr, 0);S[i] = lr[0];S[i + 1] = lr[1];}}private static int streamtoword(byte data[], int offp[]) {int i;int word = 0;int off = offp[0];for (i = 0; i < 4; i++) {word = (word << 8) | (data[off] & 0xff);off = (off + 1) % data.length;}offp[0] = off;return word;}private static void encipher(int lr[], int off) {int i, n, l = lr[off], r = lr[off + 1];l ^= P[0];for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2; ) {// Feistel substitution on left wordn = S[(l >> 24) & 0xff];n += S[0x100 | ((l >> 16) & 0xff)];n ^= S[0x200 | ((l >> 8) & 0xff)];n += S[0x300 | (l & 0xff)];r ^= n ^ P[++i];// Feistel substitution on right wordn = S[(r >> 24) & 0xff];n += S[0x100 | ((r >> 16) & 0xff)];n ^= S[0x200 | ((r >> 8) & 0xff)];n += S[0x300 | (r & 0xff)];l ^= n ^ P[++i];}lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];lr[off + 1] = l;}private static void key(byte key[]) {int i;int koffp[] = {0};int lr[] = {0, 0};int plen = P.length, slen = S.length;for (i = 0; i < plen; i++) {P[i] = P[i] ^ streamtoword(key, koffp);}for (i = 0; i < plen; i += 2) {encipher(lr, 0);P[i] = lr[0];P[i + 1] = lr[1];}for (i = 0; i < slen; i += 2) {encipher(lr, 0);S[i] = lr[0];S[i + 1] = lr[1];}}public static boolean matches(CharSequence rawPassword, String encodedPassword) {if (encodedPassword == null || encodedPassword.length() == 0) {return false;}if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {return false;}return checkpw(rawPassword.toString(), encodedPassword);}public static boolean checkpw(String plaintext, String hashed) {return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));}static boolean equalsNoEarlyReturn(String a, String b) {char[] caa = a.toCharArray();char[] cab = b.toCharArray();if (caa.length != cab.length) {return false;}byte ret = 0;for (int i = 0; i < caa.length; i++) {ret |= caa[i] ^ cab[i];}return ret == 0;}
}

单元测试:

package com.iscas.common.tools.core.security;import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;import java.security.SecureRandom;/*** BcryptUtils测试** @author zhuquanwen* @version 1.0* @date 2021/3/14 13:03* @since jdk1.8*/
public class BCryptUtilsTests {/*** 测试Bcrypt加解密* */@Testpublic void testBcrypt() {//10是不确定的  此处只是个例子String salt = BCryptUtils.gensalt(10, new SecureRandom());String str = BCryptUtils.hashpw("123456", salt);boolean result = BCryptUtils.checkpw("123456", str);Assertions.assertEquals(result, true);}
}

4、Http Basic

工具类:

import java.util.Base64;/*** @author zhuquanwen* @version 1.0* @date 2023/1/20 8:42*/
public class HttpBasicUtils {private HttpBasicUtils() {}public static String createAuthorizationVal(String username, String pwd) {String authStr = username + ":" + pwd;byte[] authEncBytes = Base64.getEncoder().encode(authStr.getBytes());return "Basic " + new String(authEncBytes);}}

5、MD5

MD5为单向加密
引入依赖(MAVEN):

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>

引入依赖(gradle):

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'

工具类:

package com.iscas.common.tools.core.security;import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.jetbrains.annotations.NotNull;import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Random;/*** MD5加密解密工具类** @author zhuquanwen* @date 2018/7/13**/@SuppressWarnings({"unused", "AlibabaLowerCamelCaseVariableNaming", "AlibabaClassNamingShouldBeCamel"})
public final class MD5Utils {private static final int LENGTH_16 = 16;private static final int LENGTH_48 = 48;private static final int NUMBER_3 = 3;private static final String DEFAULT_CHARSET = "UTF-8";private MD5Utils() {}/*** MD5加密,不带盐** @param input   输入字符串* @param charset 编码* @return java.lang.String* @throws NoSuchAlgorithmException 获取MessageDigest对象失败 {@link MessageDigest}* @date 2018/7/14*/@SuppressWarnings("UnusedAssignment")public static String md5(String input, String charset) throws NoSuchAlgorithmException, UnsupportedEncodingException {assert StringUtils.isNotBlank(input);byte[] byteArray = input.getBytes(charset);return doMd5(byteArray);}/*** MD5加密,不带盐** @param input 输入字符串* @return java.lang.String* @throws NoSuchAlgorithmException 获取MessageDigest对象失败 {@link MessageDigest}* @date 2018/7/14*/@SuppressWarnings("UnusedAssignment")public static String md5(String input) throws NoSuchAlgorithmException {try {return md5(input, DEFAULT_CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** MD5加密,自动生成盐** @param str     要加密的串* @param charset 编码格式* @return java.lang.String* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static String saltMD5(String str, String charset) throws NoSuchAlgorithmException, UnsupportedEncodingException {assert StringUtils.isNotBlank(str);Random r = new Random();StringBuilder sb = new StringBuilder(16);sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));int len = sb.length();if (len < LENGTH_16) {sb.append("0".repeat(Math.max(0, LENGTH_16 - len)));}String salt = sb.toString();str = doMd5((str + salt).getBytes(charset));char[] cs = new char[LENGTH_48];for (int i = 0; i < LENGTH_48; i += NUMBER_3) {cs[i] = str.charAt(i / 3 * 2);char c = salt.charAt(i / 3);cs[i + 1] = c;cs[i + 2] = str.charAt(i / 3 * 2 + 1);}return new String(cs);}/*** MD5加密,自动生成盐** @param str 要加密的串* @return java.lang.String* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static String saltMD5(String str) throws NoSuchAlgorithmException {try {return saltMD5(str, DEFAULT_CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 加密校验** @param str 明文* @param md5 密文* @return boolean 校验成功与否* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static boolean saltVerify(String str, String md5) throws NoSuchAlgorithmException {try {return saltVerify(str, md5, DEFAULT_CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 加密校验** @param str     明文* @param md5     密文* @param charset 编码格式* @return boolean 校验成功与否* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static boolean saltVerify(String str, String md5, String charset) throws NoSuchAlgorithmException, UnsupportedEncodingException {assert StringUtils.isNotBlank(str);assert StringUtils.isNotBlank(md5);char[] cs1 = new char[32];char[] cs2 = new char[16];for (int i = 0; i < LENGTH_48; i += NUMBER_3) {cs1[i / 3 * 2] = md5.charAt(i);cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);cs2[i / 3] = md5.charAt(i + 1);}String salt = new String(cs2);return doMd5((str + salt).getBytes(charset)).equals(new String(cs1));}/*** hmacMD5** @param key     密钥* @param input   输入字符串* @param charset 编码格式* @return java.lang.String* @date 2018/7/14*/@SuppressWarnings("UnusedAssignment")public static String hmacMd5(String key, String input, String charset) throws UnsupportedEncodingException {byte[] bytes = input.getBytes(charset);byte[] keyBytes = key.getBytes(charset);byte[] hmacResult = doHmacMd5(keyBytes, bytes);return ByteUtils.toHexString(hmacResult);}/*** hmacMD5** @param key   密钥* @param input 输入字符串* @return java.lang.String* @date 2018/7/14*/@SuppressWarnings("UnusedAssignment")public static String hmacMd5(String key, String input) {try {return hmacMd5(key, input, DEFAULT_CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** HMAC校验** @param str     明文* @param md5     密文* @param charset 编码格式* @return boolean 校验成功与否* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static boolean hmacVerify(String key, String str, String md5, String charset) throws UnsupportedEncodingException {assert StringUtils.isNotBlank(str);assert StringUtils.isNotBlank(md5);assert StringUtils.isNotBlank(key);assert StringUtils.isNotBlank(charset);byte[] src = ByteUtils.fromHexString(md5);byte[] keyBytes = key.getBytes(charset);byte[] strBytes = str.getBytes(charset);byte[] target = doHmacMd5(keyBytes, strBytes);return Arrays.equals(src, target);}/*** HMAC校验** @param str 明文* @param md5 密文* @return boolean 校验成功与否* @date 2018/7/14*/@SuppressWarnings("AlibabaUndefineMagicConstant")public static boolean hmacVerify(String key, String str, String md5) {try {return hmacVerify(key, str, md5, DEFAULT_CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}//    /**
//     * 获取十六进制字符串形式的MD5摘要
//     */
//    private static String md5Hex(String src) throws NoSuchAlgorithmException {//        MessageDigest md5 = MessageDigest.getInstance("md5");
//        byte[] bs = md5.digest(src.getBytes());
//        return new String(new Hex().encode(bs));
//
//    }/*** MD5加密,不带盐** @param input 输入字符串* @return java.lang.String* @throws NoSuchAlgorithmException 获取MessageDigest对象失败 {@link MessageDigest}* @date 2018/7/14*/public static String doMd5(byte[] input) throws NoSuchAlgorithmException {assert input != null;MessageDigest md5 = MessageDigest.getInstance("md5");byte[] md5Bytes = md5.digest(input);return toHexString(md5Bytes);}/*** 获取一个文件的md5值(可处理大文件)** @return md5 value*/public static String getFileMD5(InputStream is) {try {MessageDigest MD5 = MessageDigest.getInstance("MD5");byte[] buffer = new byte[8192];int length;while ((length = is.read(buffer)) != -1) {MD5.update(buffer, 0, length);}return new String(Hex.encodeHex(MD5.digest()));} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}}}private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};private static String toHexString(byte[] input) {String result = "";for (int i = 0; i < input.length; i++) {result += HEX_CHARS[(input[i] >>> 4) & 0x0f];result += HEX_CHARS[(input[i]) & 0x0f];}return result;}@NotNullprivate static byte[] doHmacMd5(byte[] keyBytes, byte[] bytes) {Digest mg = new MD5Digest();HMac hMac = new HMac(mg);hMac.init(new KeyParameter(keyBytes));hMac.update(bytes, 0, bytes.length);byte[] hmacResult = new byte[hMac.getMacSize()];hMac.doFinal(hmacResult, 0);return hmacResult;}}

单元测试:

package com.iscas.common.tools.core.security;import com.iscas.common.tools.core.reflect.reflectTest.A;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;/*** MD5工具类测试* @author zhuquanwen**/public class MD5UtilsTests {/*** 普通加密* */@Testpublic void MD51() throws NoSuchAlgorithmException {String sec = MD5Utils.md5("apply");Assertions.assertNotNull(sec);}/*** 加盐加密* */@Testpublic void MD52() throws NoSuchAlgorithmException {String sec = MD5Utils.saltMD5("admin");System.out.println(sec);Assertions.assertNotNull(sec);}/*** 加盐加密的校验* */@Testpublic void MD53() throws NoSuchAlgorithmException {boolean sec = MD5Utils.saltVerify("admin","f2020e118a4aa8fd39a4560c79b16b30024fb29b64242b5e");Assertions.assertEquals(true, sec);}/*** hmac加密* */@Testpublic void MD54() {String iscas = MD5Utils.hmacMd5("iscas", "123456");System.out.println(iscas);Assertions.assertNotNull(iscas);}/*** hmac校验* */@Testpublic void MD55() {String data = MD5Utils.hmacMd5("iscas", "123456");System.out.println(data);boolean res = MD5Utils.hmacVerify("iscas", "123456", data);Assertions.assertTrue(res);}/*** 获取大文件MD5码* */@Test@Disabledpublic void testFileMD5() throws FileNotFoundException {long start = System.currentTimeMillis();String fileMD5 = MD5Utils.getFileMD5(new FileInputStream("G:/cs-video/dist/fe8fc15215877f8422c43dfa408c1518.store"));Assertions.assertNotNull(fileMD5);System.out.println(fileMD5);long end = System.currentTimeMillis();System.out.printf("耗时:%dms", (end - start));}
}

6、RSA

RSA为非对称加密
工具类:

package com.iscas.common.tools.core.security;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;/*** RSA工具类** @author zhuquanwen* @version 1.0* @date 2019/9/27 15:48* @since jdk1.8*/@SuppressWarnings("unused")
public class RsaUtils {private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjh7unmMBs" +"QrAxJRHd3iXZD65fZClHxyEjxTzQB5F/UbYmyrEBzZfgw7u0UgSqnc+SQX+HUScHuMG+eC+KotoNPY1JlOC8x" +"A358khG6rBB3WDIqoZJ3PnZP3DkJ0IM8RO70xMFmqnQhWuGKrC28vOpqwopo8GvEaCoq7ec39/oJhV7skoYt+X" +"fYGLld9HVaKZyAvpbZSXhoX8GAOlXpAukhjuRZfyX0+313ZS4DUYibqczwHS6KNR8Cv5bz6lZACwaLIruZtdyD" +"7XacjHsDlHEqSgPPqRCRJNk3KC82dyyLWfEAEwb/CHMfQrTAUeCJuMbwmcZ5HJ9P5lXb6zBH5rgwIDAQAB";private static final String PRIVATE_KEY = "RSA私钥Base64编码:MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjA" +"gEAAoIBAQCOHu6eYwGxCsDElEd3eJdkPrl9kKUfHISPFPNAHkX9RtibKsQHNl+DDu7RSBKqdz5JBf4dRJwe4wb5" +"4L4qi2g09jUmU4LzEDfnySEbqsEHdYMiqhknc+dk/cOQnQgzxE7vTEwWaqdCFa4YqsLby86mrCimjwa8RoKirt5" +"zf3+gmFXuyShi35d9gYuV30dVopnIC+ltlJeGhfwYA6VekC6SGO5Fl/JfT7fXdlLgNRiJupzPAdLoo1HwK/lvPq" +"VkALBosiu5m13IPtdpyMewOUcSpKA8+pEJEk2TcoLzZ3LItZ8QATBv8Icx9CtMBR4Im4xvCZxnkcn0/mVdvrME" +"fmuDAgMBAAECggEAA4Ye0oyP6SzkFLu8fejekBzCCqwAfCH/43BYi7l0cNBF5KsNy0P84EoJf+TymYl1YOgmIe" +"GmoVltvdplvLZSMiX8sWOWtqIrULL7AC2etamjQ8PF9eV40lc8dyR9pJL0hhh1NoUUep4BABmT1VFbYWSZaW/Yc" +"eipqpD9cQ2zQ28aDvQR0j1B0qEeWnfGqYYQKzR/v7MoXqOfrVJ1Jo7CbUbBuvwkr01RRl03k0u+cGFpq6gbp9i" +"GXJ7M7ss83+bZXKdjTzrXCEASQ68YJ4MvexL7mp+4L79eBrUOh/TGCOJazDTxa1PfKCE5FaD8TBrDFtle07EPV" +"I0XYASsvFp6KQKBgQDMf5qlwL4s524Eeg/W/xxFdpNX8TrWlGWrrGb/CCsKwIepRCNkwP98cCG75pB0EpyCRwGh" +"wbDOhzgbt7TbfqafpvIB5LyeQNAktYiPbMZTXDV1o3SVa5RKPiT/tW2Ponhbqp17kjJdSJyDD9eYXxrLQTsQ88" +"milC6nD3HalKme7QKBgQCx6bn3or+TP8EjS13VRd5xGwPW7csDTS87AO/pwvQHnRQGgOx987Lq856kcVJy+ocs" +"es1qWIsiqJKT5TKQh6jzYB2/PPq/rB9gCPM1fV6hb8iy7rNiQbe1LrFawK9fgEo7RewxmBCjN0OdtA22AyIL" +"IC+jtBNL1LGB84zYRl12LwKBgBXi2kQ/GptnsWidP7C84OO2SxKwaKGqhC8ZZnSJBUJDVMGS307bMPy6a4HWrUM" +"e8s0mmFAdkLSp2CFvSdXr+h1AGsqFFoLBYQVswE7JT3iAd+A9PC75soc3m3Iakr06oDL/UZd2EBnXuZh1S5etJg" +"r20kGANeZGga+zgXXpTzYJAoGBAI0bbmbtSvqz5zBiF0MPTlTw80OliI3OyvYGUUJbYIclW3upB2kCP1a/8IRGa" +"PlOoKVzpLaDEZ9kihUJBOjC4ApfolhKOiqJjrzxfExhaguqiEj6r4Xvz4/BP+NVzgJ10upeE+5lyFRbgaJz6yg" +"AJiEi3wX8zg0n3b3O+FeUv437AoGAVzH3ITlUWkiv438TxUREJlppZLOW/vDzhuueU5BnbwSP21tmClpWnM0lYZ" +"KgpagUVG0AWklv+HOGP9OaTwW9Pectz3nCtOoAVUdPFNAlHgu+I6wsNVMAlQALfLMMh9CJssbWG+21O196oO6Q" +"QsGqllLZFDy77TJQy0hgWnttcWM=";/*** 生成秘钥对* @since jdk1.8* @date 2021/1/6* @throws Exception 异常* @return java.security.KeyPair*/public static KeyPair getKeyPair() throws Exception {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);return keyPairGenerator.generateKeyPair();}/*** 获取公钥(Base64编码)* @since jdk1.8* @date 2021/1/6* @param keyPair 密钥对* @return java.lang.String*/public static String getPublicKey(KeyPair keyPair){PublicKey publicKey = keyPair.getPublic();byte[] bytes = publicKey.getEncoded();return byte2Base64(bytes);}/*** 获取私钥(Base64编码)* @since jdk1.8* @date 2021/1/6* @param keyPair 密钥对* @return java.lang.String*/public static String getPrivateKey(KeyPair keyPair){PrivateKey privateKey = keyPair.getPrivate();byte[] bytes = privateKey.getEncoded();return byte2Base64(bytes);}/*** 将Base64编码后的公钥转换成PublicKey对象* @since jdk1.8* @date 2021/1/6* @param pubStr 公钥* @return java.security.PublicKey*/public static PublicKey string2PublicKey(String pubStr) throws Exception{byte[] keyBytes = base642Byte(pubStr);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(keySpec);}/*** 将Base64编码后的私钥转换成PrivateKey对象* @since jdk1.8* @date 2021/1/6* @param priStr 私钥* @return java.security.PrivateKey*/public static PrivateKey string2PrivateKey(String priStr) throws Exception{byte[] keyBytes = base642Byte(priStr);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePrivate(keySpec);}/**公钥加密*/private static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception{Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(content);}/**私钥解密*/private static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception{Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(content);}/**字节数组转Base64编码*/private static String byte2Base64(byte[] bytes){Base64.Encoder encoder = Base64.getEncoder();return encoder.encodeToString(bytes);}/**Base64编码转字节数组*/private static byte[] base642Byte(String base64Key) {Base64.Decoder decoder = Base64.getDecoder();return decoder.decode(base64Key);}/*** RSA 加密* @since jdk1.8* @date 2019/9/27* @param str 待加密的字符串* @param publicKeyStr 公钥字符串* @param charset 编码格式* @return java.lang.String*/public static String encrypt(String str, String publicKeyStr, String charset) throws Exception {//将Base64编码后的公钥转换成PublicKey对象if (publicKeyStr == null) {publicKeyStr = PUBLIC_KEY;}if (charset == null) {charset = "utf-8";}PublicKey publicKey = string2PublicKey(publicKeyStr);//用公钥加密byte[] publicEncrypt = RsaUtils.publicEncrypt(str.getBytes(charset), publicKey);//加密后的内容Base64编码return RsaUtils.byte2Base64(publicEncrypt);}/*** RSA解密* @since jdk1.8* @date 2019/9/27* @param str 待解密的字符串* @param privateKeyStr 私钥字符串* @param charset 编码格式* @return java.lang.String*/public static String decrypt(String str, String privateKeyStr, String charset) throws Exception {if (privateKeyStr == null) {privateKeyStr = PRIVATE_KEY;}if (charset == null) {charset = "utf-8";}PrivateKey privateKey = RsaUtils.string2PrivateKey(privateKeyStr);//加密后的内容Base64解码byte[] base642Byte = RsaUtils.base642Byte(str);//用私钥解密byte[] privateDecrypt = RsaUtils.privateDecrypt(base642Byte, privateKey);return new String(privateDecrypt, charset);}
}

单元测试:

package com.iscas.common.tools.core.security;import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;import java.security.KeyPair;/*** @author zhuquanwen* @version 1.0* @date 2019/9/27 15:51* @since jdk1.8*/
public class RsaUtilsTests {@Testpublic void testRSA() {try {//===============生成公钥和私钥,公钥传给客户端,私钥服务端保留==================//生成RSA公钥和私钥,并Base64编码KeyPair keyPair = RsaUtils.getKeyPair();String publicKeyStr = RsaUtils.getPublicKey(keyPair);String privateKeyStr = RsaUtils.getPrivateKey(keyPair);System.out.println("RSA公钥Base64编码:" + publicKeyStr);System.out.println("RSA私钥Base64编码:" + privateKeyStr);//=========================使用公钥加密String encrypt = RsaUtils.encrypt("祖国", publicKeyStr, "utf-8");Assertions.assertNotNull(encrypt);//=========================使用私钥解密String decrypt = RsaUtils.decrypt(encrypt, privateKeyStr, "utf-8");Assertions.assertNotNull(decrypt);} catch (Exception e) {e.printStackTrace();}}}

7、SHA256

SHA为单向加密

引入依赖(MAVEN):

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>

引入依赖(gradle):

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'

工具类:

package com.iscas.common.tools.core.security;import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.jetbrains.annotations.NotNull;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;/*** SHA256加密工具类** @author zhuquanwen* @version 1.0* @date 2021/3/14 13:22* @since jdk1.8*/
@SuppressWarnings("unused")
public class Sha256Utils {private static final String DEFAULT_ENCODING = "UTF-8";private Sha256Utils() {}/*** 利用java原生的摘要实现SHA256加密** @param str 待加密的报文* @return String*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static String encrypt(String str) throws NoSuchAlgorithmException {try {return encrypt(str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 利用java原生的摘要实现SHA256加密** @param str     待加密的报文* @param charset 编码格式* @return String*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static String encrypt(String str, String charset) throws NoSuchAlgorithmException, UnsupportedEncodingException {MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");messageDigest.update(str.getBytes(charset));return toHexString(messageDigest.digest());}/*** hmac-sha256加密** @param key     秘钥* @param str     待加密的报文* @param charset 编码格式* @return String*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static String hmacEncrypt(String key, String str, String charset) throws UnsupportedEncodingException {byte[] keyBytes = key.getBytes(charset);byte[] strBytes = str.getBytes(charset);byte[] hmacResult = doHmac(keyBytes, strBytes);return toHexString(hmacResult);}/*** hmac-sha256加密** @param key 秘钥* @param str 待加密的报文* @return String*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static String hmacEncrypt(String key, String str) {try {return hmacEncrypt(key, str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** hmac-sha256加密** @param key     秘钥* @param str     待校验的报文* @param sha     加密后的串* @param charset 编码格式* @return boolean*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static boolean hmacVerify(String key, String str, String sha, String charset) throws UnsupportedEncodingException {assert StringUtils.isNotBlank(sha);assert StringUtils.isNotBlank(str);assert StringUtils.isNotBlank(key);assert StringUtils.isNotBlank(charset);byte[] src = ByteUtils.fromHexString(sha);byte[] keyBytes = key.getBytes(charset);byte[] strBytes = str.getBytes(charset);byte[] target = doHmac(keyBytes, strBytes);return Arrays.equals(src, target);}/*** hmac-sha256加密** @param key 秘钥* @param str 待校验的报文* @param sha 加密后的串* @return boolean*/@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static boolean hmacVerify(String key, String str, String sha) {try {return hmacVerify(key, str, sha, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}@NotNullprivate static byte[] doHmac(byte[] keyBytes, byte[] strBytes) {Digest mg = new SHA256Digest();HMac hMac = new HMac(mg);hMac.init(new KeyParameter(keyBytes));hMac.update(strBytes, 0, strBytes.length);byte[] hmacResult = new byte[hMac.getMacSize()];hMac.doFinal(hmacResult, 0);return hmacResult;}private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};private static String toHexString(byte[] input) {String result = "";for (int i = 0; i < input.length; i++) {result += HEX_CHARS[(input[i] >>> 4) & 0x0f];result += HEX_CHARS[(input[i]) & 0x0f];}return result;}//    /**
//     * 将byte转为16进制
//     *
//     * @param bytes bytes
//     * @return String
//     */
//    private static String byte2Hex(byte[] bytes) {//        StringBuilder stringBuffer = new StringBuilder();
//        String temp;
//        for (byte aByte : bytes) {//            temp = Integer.toHexString(aByte & 0xFF);
//            if (temp.length() == 1) {//                //1得到一位的进行补0操作
//                stringBuffer.append("0");
//            }
//            stringBuffer.append(temp);
//        }
//        return stringBuffer.toString();
//    }
}

单元测试:

package com.iscas.common.tools.core.security;import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;/***** @author zhuquanwen* @version 1.0* @date 2021/3/14 13:36* @since jdk1.8*/
public class Sha256UtilsTests {@Testpublic void test() throws UnsupportedEncodingException, NoSuchAlgorithmException {String sha256Str = Sha256Utils.encrypt("123456");System.out.println(sha256Str);}@Testpublic void test2() {String iscas = Sha256Utils.hmacEncrypt("iscas", "123456");System.out.println(iscas);Assertions.assertNotNull(iscas);}@Testpublic void test3() {String sha = Sha256Utils.hmacEncrypt("iscas", "123456");System.out.println(sha);boolean res = Sha256Utils.hmacVerify("iscas", "123456", sha);Assertions.assertTrue(res);}
}

8、SM3

sm3为单向加密
引入依赖(MAVEN):

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>

引入依赖(gradle):

// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'

工具类:

package com.iscas.common.tools.core.security;import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Arrays;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 9:13*/
public class Sm3Utils {private static final String DEFAULT_ENCODING = "UTF-8";private Sm3Utils() {}static {Security.addProvider(new BouncyCastleProvider());}/*** 不使用密钥* sm3算法加密** @param str 待加密字符串* @return 返回加密后,固定长度=64的16进制字符串*/public static String encrypt(String str) {try {return encrypt(str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 不使用密钥* sm3算法加密** @param str 待加密字符串* @param charset 编码格式* @return 返回加密后,固定长度=64的16进制字符串*/public static String encrypt(String str, String charset) throws UnsupportedEncodingException {// 将返回的hash值转换成16进制字符串String resultHexString = "";// 将字符串转换成byte数组byte[] srcData = str.getBytes(charset);// 调用hashbyte[] resultHash = hash(srcData);// 将返回的hash值转换成16进制字符串return ByteUtils.toHexString(resultHash);}/*** 使用密钥* sm3算法加密** @param key 密钥key* @param str 待加密字符串* @return 返回加密后,固定长度=64的16进制字符串*/public static String hmacEncrypt(String key, String str) {try {return hmacEncrypt(key, str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 使用密钥* sm3算法加密** @param key 密钥key* @param str 待加密字符串* @param charset 编码格式* @return 返回加密后,固定长度=64的16进制字符串*/public static String hmacEncrypt(String key, String str, String charset) throws UnsupportedEncodingException {byte[] keyBytes = key.getBytes(charset);byte[] strBytes = str.getBytes(charset);byte[] hmac = hmac(keyBytes, strBytes);return ByteUtils.toHexString(hmac);}/*** 判断源数据与加密数据是否一致* 通过验证原数组和生成的hash数组是否为同一数组,验证两者是否为同意数据** @param srcStr 源字符串* @param sm3Str 加密后的数据* @return 校验结果*/public static boolean verify(String srcStr, String sm3Str) {try {return verifyUseCharset(srcStr, sm3Str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 判断源数据与加密数据是否一致* 通过验证原数组和生成的hash数组是否为同一数组,验证两者是否为同意数据** @param srcStr 源字符串* @param sm3Str 加密后的数据* @param charset 编码格式* @return 校验结果*/public static boolean verifyUseCharset(String srcStr, String sm3Str, String charset) throws UnsupportedEncodingException {byte[] srcData = srcStr.getBytes(charset);byte[] sm3Hash = ByteUtils.fromHexString(sm3Str);//通过摘要加密生成新的hash数组byte[] newHash = hash(srcData);return Arrays.equals(newHash, sm3Hash);}/*** 判断源数据与加密数据是否一致,使用HMAC* 通过验证原数组和生成的hash数组是否为同一数组,验证两者是否为同意数据** @param srcStr 源字符串* @param sm3Str 加密后的数据* @return 校验结果*/public static boolean hmacVerify(String key, String srcStr, String sm3Str) {try {return hmacVerifyUseCharset(key, srcStr, sm3Str, DEFAULT_ENCODING);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}/*** 判断源数据与加密数据是否一致,使用HMAC* 通过验证原数组和生成的hash数组是否为同一数组,验证两者是否为同意数据** @param srcStr 源字符串* @param sm3Str 加密后的数据* @param charset 编码格式* @return 校验结果*/public static boolean hmacVerifyUseCharset(String key, String srcStr, String sm3Str, String charset) throws UnsupportedEncodingException {byte[] keyData = key.getBytes(charset);byte[] srcData = srcStr.getBytes(charset);byte[] sm3Hash = ByteUtils.fromHexString(sm3Str);//通过摘要加密生成新的hash数组byte[] newHash = hmac(keyData, srcData);return Arrays.equals(newHash, sm3Hash);}/*** 返回长度=32的byte数组* 生成对应的hash值** @param srcData* @return byte[]*/public static byte[] hash(byte[] srcData) {//摘要加密SM3Digest digest = new SM3Digest();//使用指定的数组更新摘要digest.update(srcData, 0, srcData.length);//获取摘要的长度byte[] hash = new byte[digest.getDigestSize()];digest.doFinal(hash, 0);return hash;}/*** 通过密钥进行加密* 指定密钥进行加密** @param key     密钥* @param srcData 被加密的byte数组* @return byte[]*/public static byte[] hmac(byte[] key, byte[] srcData) {KeyParameter keyParameter = new KeyParameter(key);SM3Digest digest = new SM3Digest();HMac mac = new HMac(digest);mac.init(keyParameter);mac.update(srcData, 0, srcData.length);byte[] result = new byte[mac.getMacSize()];mac.doFinal(result, 0);return result;}========================================下面的方式为使用JDK原生实现,但无法使用Hmac,暂时注释掉=================================
//
//    private static char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
//    public static final byte[] IV = {0x73, (byte) 0x80, 0x16, 0x6f, 0x49, 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42,
//            (byte) 0xd7, (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30, (byte) 0xbc, (byte) 0x16, 0x31,
//            0x38, (byte) 0xaa, (byte) 0xe3, (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e, 0x4e};
//    private static final Integer TJ_15 = Integer.valueOf("79cc4519", 16);
//    private static final Integer TJ_63 = Integer.valueOf("7a879d8a", 16);
//    private static final byte[] FirstPadding = {(byte) 0x80};
//    private static final byte[] ZeroPadding = {(byte) 0x00};
//
//
//    public static String encrypt(String source) throws IOException {//        byte[] bytes = encrypt(source.getBytes(StandardCharsets.UTF_8));
//        return bytesToHexString(bytes);
//    }
//
//    public static byte[] encrypt(byte[] source) throws IOException {//        byte[] m1 = padding(source);
//        int n = m1.length / (512 / 8);
//
//        byte[] b;
//        byte[] vi = IV.clone();
//        byte[] vi1 = null;
//        for (int i = 0; i < n; i++) {//            b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
//            vi1 = CF(vi, b);
//            vi = vi1;
//        }
//        return vi1;
//    }
//
//
//    private static int T(int j) {//        if (j >= 0 && j <= 15) {//            return TJ_15.intValue();
//        } else if (j >= 16 && j <= 63) {//            return TJ_63.intValue();
//        } else {//            throw new RuntimeException("data invalid");
//        }
//    }
//
//    private static Integer FF(Integer x, Integer y, Integer z, int j) {//        if (j >= 0 && j <= 15) {//            return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
//        } else if (j >= 16 && j <= 63) {//            return Integer.valueOf(
//                    (x.intValue() & y.intValue()) | (x.intValue() & z.intValue()) | (y.intValue() & z.intValue()));
//        } else {//            throw new RuntimeException("data invalid");
//        }
//    }
//
//    private static Integer GG(Integer x, Integer y, Integer z, int j) {//        if (j >= 0 && j <= 15) {//            return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
//        } else if (j >= 16 && j <= 63) {//            return Integer.valueOf((x.intValue() & y.intValue()) | (~x.intValue() & z.intValue()));
//        } else {//            throw new RuntimeException("data invalid");
//        }
//    }
//
//    private static Integer P0(Integer x) {//        return Integer
//                .valueOf(x.intValue() ^ Integer.rotateLeft(x.intValue(), 9) ^ Integer.rotateLeft(x.intValue(), 17));
//    }
//
//    private static Integer P1(Integer x) {//        return Integer.valueOf(x.intValue() ^ Integer.rotateLeft(x.intValue(), 15) ^ Integer.rotateLeft(x.intValue(), 23));
//    }
//
//    private static byte[] padding(byte[] source) throws IOException {//        if (source.length >= 0x2000000000000000L) {//            throw new RuntimeException("src data invalid.");
//        }
//        long l = source.length * 8;
//        long k = 448 - (l + 1) % 512;
//        if (k < 0) {//            k = k + 512;
//        }
//
//        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();) {//            baos.write(source);
//            baos.write(FirstPadding);
//            long i = k - 7;
//            while (i > 0) {//                baos.write(ZeroPadding);
//                i -= 8;
//            }
//            baos.write(long2bytes(l));
//            return baos.toByteArray();
//        }
//    }
//
//    private static byte[] long2bytes(long l) {//        byte[] bytes = new byte[8];
//        for (int i = 0; i < 8; i++) {//            bytes[i] = (byte) (l >>> ((7 - i) * 8));
//        }
//        return bytes;
//    }
//
//    private static byte[] CF(byte[] vi, byte[] bi) throws IOException {//        int a, b, c, d, e, f, g, h;
//        a = toInteger(vi, 0);
//        b = toInteger(vi, 1);
//        c = toInteger(vi, 2);
//        d = toInteger(vi, 3);
//        e = toInteger(vi, 4);
//        f = toInteger(vi, 5);
//        g = toInteger(vi, 6);
//        h = toInteger(vi, 7);
//
//        int[] w = new int[68];
//        int[] w1 = new int[64];
//        for (int i = 0; i < 16; i++) {//            w[i] = toInteger(bi, i);
//        }
//        for (int j = 16; j < 68; j++) {//            w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15)) ^ Integer.rotateLeft(w[j - 13], 7)
//                    ^ w[j - 6];
//        }
//        for (int j = 0; j < 64; j++) {//            w1[j] = w[j] ^ w[j + 4];
//        }
//        int ss1, ss2, tt1, tt2;
//        for (int j = 0; j < 64; j++) {//            ss1 = Integer.rotateLeft(Integer.rotateLeft(a, 12) + e + Integer.rotateLeft(T(j), j), 7);
//            ss2 = ss1 ^ Integer.rotateLeft(a, 12);
//            tt1 = FF(a, b, c, j) + d + ss2 + w1[j];
//            tt2 = GG(e, f, g, j) + h + ss1 + w[j];
//            d = c;
//            c = Integer.rotateLeft(b, 9);
//            b = a;
//            a = tt1;
//            h = g;
//            g = Integer.rotateLeft(f, 19);
//            f = e;
//            e = P0(tt2);
//        }
//        byte[] v = toByteArray(a, b, c, d, e, f, g, h);
//        for (int i = 0; i < v.length; i++) {//            v[i] = (byte) (v[i] ^ vi[i]);
//        }
//        return v;
//    }
//
//    private static int toInteger(byte[] source, int index) {//        StringBuilder valueStr = new StringBuilder("");
//        for (int i = 0; i < 4; i++) {//            valueStr.append(chars[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);
//            valueStr.append(chars[(byte) (source[index * 4 + i] & 0x0F)]);
//        }
//        return Long.valueOf(valueStr.toString(), 16).intValue();
//
//    }
//
//    private static byte[] toByteArray(int a, int b, int c, int d, int e, int f, int g, int h) throws IOException {
//        try (ByteArrayOutputStream baos = new ByteArrayOutputStream(32);) {
//            baos.write(toByteArray(a));
//            baos.write(toByteArray(b));
//            baos.write(toByteArray(c));
//            baos.write(toByteArray(d));
//            baos.write(toByteArray(e));
//            baos.write(toByteArray(f));
//            baos.write(toByteArray(g));
//            baos.write(toByteArray(h));
//            return baos.toByteArray();
//        }
//    }
//
//    private static byte[] toByteArray(int i) {//        byte[] byteArray = new byte[4];
//        byteArray[0] = (byte) (i >>> 24);
//        byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);
//        byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);
//        byteArray[3] = (byte) (i & 0xFF);
//        return byteArray;
//    }
//
//    private static String byteToHexString(byte ib) {
//        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
//        char[] ob = new char[2];
//        ob[0] = Digit[(ib >>> 4) & 0X0f];
//        ob[1] = Digit[ib & 0X0F];
//        return new String(ob);
//    }
//
//    private static String bytesToHexString(byte[] bytes) {
//        StringBuilder sb = new StringBuilder();
//        for (byte aByte : bytes) {
//            sb.append(byteToHexString(aByte));
//        }
//        return sb.toString();
//    }
}

单元测试:

package com.iscas.common.tools.core.security;import org.junit.jupiter.api.Test;import java.io.IOException;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 13:34*/
class Sm3UtilsTest {/*** 测试普通sm3加密*/@Testpublic void testEncode() {System.out.println(Sm3Utils.encrypt("123456"));}/*** 测试使用密钥hmac加密*/@Testpublic void testEncode2() {System.out.println(Sm3Utils.hmacEncrypt("iscas", "123456"));System.out.println(Sm3Utils.hmacEncrypt("ISCAS", "123456"));}/*** 测试普通加密校验*/@Testpublic void testVerify() {System.out.println(Sm3Utils.verify("123456", "207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb"));}/*** 测试HMAC加密校验*/@Testpublic void testHmacVerify() {System.out.println(Sm3Utils.hmacVerify("iscas", "123456", "a0bc6c6ac39712c81f805c8a80407892b1006ee27a04c2b0a15fec84b5065225"));}}

9、SM4

sm4为对称加密
工具类:

package com.iscas.common.tools.core.security;import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 17:03*/
public class Sm4Utils {private Sm4Utils() {}// 初始化算法提供者信息.static {Security.addProvider(new BouncyCastleProvider());}/*** 数据编码.*/private static final String CHARSET_UTF8 = "UTF-8";/*** 秘钥空间大小.*/public static final int SM4_KEY_SIZE = 128;/*** 默认秘钥空间为128,Key的长度是16.*/public static final int SM4_KEY_LENGTH = 16;/*** 算法编号.*/public static final String SM4_NAME = "SM4";/*** CBC模式串.*/public static final String SM4_NAME_ECB = "SM4/CBC/PKCS5Padding";//    /**
//     * 首次加密初始向量.
//     */
//    public static final byte[] SM4_KEY_IV = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31};/*** 密钥*/public static final String CRYPT_KEY = "10f5dd7c2d45d247";private static final String CKEY = "encryptionIntVec";/*** 对文本内容进行加密.** @param plainText 待加密明文内容.* @return 加密的密文.*/public static String encrypt(String plainText) throws Exception {return encodeByCbc(plainText, CRYPT_KEY);}/*** 对文本内容进行加密.** @param plainText 待加密明文内容.* @param sm4Key    SM4秘钥.* @return 加密的密文.*/public static String encrypt(String plainText, String sm4Key) throws Exception {return encodeByCbc(plainText, sm4Key);}/*** 对文本密文进行解密.** @param cipherText 待解密密文.* @return 解密的明文.* @throws Exception .*/public static String decrypt(String cipherText) throws Exception {return decodeByCbc(cipherText, CRYPT_KEY);}/*** 对文本密文进行解密.** @param cipherText 待解密密文.* @param sm4Key     SM4秘钥.* @return 解密的明文.* @throws Exception .*/public static String decrypt(String cipherText, String sm4Key) throws Exception {return decodeByCbc(cipherText, sm4Key);}/*** 生成SM4算法的KEY.** @return 生成的SM4秘钥.* @throws Exception .*/public static String generateSm4Key() throws Exception {return Base64.getEncoder().encodeToString(generateSm4Key(SM4_KEY_SIZE));}/*** 生成SM4算法的KEY.** @param sm4Key 指定秘钥空间大小.* @return 生成的SM4秘钥.* @throws Exception .*/private static byte[] generateSm4Key(int sm4Key) throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance(SM4_NAME, BouncyCastleProvider.PROVIDER_NAME);keyGenerator.init(sm4Key, new SecureRandom());return keyGenerator.generateKey().getEncoded();}/*** 对字节数组内容进行加密.** @param plainBytes 待加密明文内容.* @param sm4Key     SM4秘钥.* @return 加密的密文.*/public static byte[] encodeBytes(byte[] plainBytes, String sm4Key) throws Exception {// 秘钥位数处理转换.sm4Key = sm4KeyPadding(sm4Key);// base64格式秘钥转换:sm4Key to byte[].byte[] sm4KeyBytes = Base64.getDecoder().decode(sm4Key);// 使用转换后的原文和秘钥进行加密操作.return encodeCbcPadding(plainBytes, sm4KeyBytes);}/*** 对字节数组密文进行解密.** @param cipherBytes 待解密密文.* @param sm4Key      SM4秘钥.* @return 解密的明文.*/public static byte[] decodeBytes(byte[] cipherBytes, String sm4Key) throws Exception {// 秘钥位数处理转换.sm4Key = sm4KeyPadding(sm4Key);// base64格式秘钥转换:sm4Key to byte[].byte[] keyBts = Base64.getDecoder().decode(sm4Key);// 使用转换后的密文和秘钥进行解密操作return decryptCbcPadding(cipherBytes, keyBts);}/*** 基于CBC模式进行SM4加密.** @param plainText 待加密明文.* @param sm4Key    Base64格式秘钥.* @return 加密后Base64格式密文.* @throws Exception 可能异常.*/private static String encodeByCbc(String plainText, String sm4Key) throws Exception {// 秘钥位数处理转换.sm4Key = sm4KeyPadding(sm4Key);// base64格式秘钥转换:sm4Key to byte[].byte[] sm4KeyBytes = Base64.getDecoder().decode(sm4Key);// String格式原文转换:plainText to byte[].byte[] plainBytes = plainText.getBytes(CHARSET_UTF8);// 使用转换后的原文和秘钥进行加密操作.byte[] cipherBytes = encodeCbcPadding(plainBytes, sm4KeyBytes);// 对加密结果使用base64进行编码:cipherBytes to Base64格式.return Base64.getEncoder().encodeToString(cipherBytes);}/*** SM4算法的CBC模式加密.** @param plainBytes 待加密明文.* @param sm4Key     Base64格式秘钥.* @return 加密后byte[]格式密文.* @throws Exception 可能异常.*/private static byte[] encodeCbcPadding(byte[] plainBytes, byte[] sm4Key) throws Exception {Cipher cipher = generateSm4EcbCipher(SM4_NAME_ECB, Cipher.ENCRYPT_MODE, sm4Key);return cipher.doFinal(plainBytes);}/*** 基于CBC模式进行SM4解密.** @param cipherText 待解密密文.* @param sm4Key     Base64格式秘钥.* @return 解密后原文.* @throws Exception 可能异常.*/private static String decodeByCbc(String cipherText, String sm4Key) throws Exception {// 秘钥位数处理转换.sm4Key = sm4KeyPadding(sm4Key);// base64格式秘钥转换:sm4Key to byte[].byte[] keyBts = Base64.getDecoder().decode(sm4Key);// base64格式密文转换:cipherText to byte[].byte[] cipherBts = Base64.getDecoder().decode(cipherText);// 使用转换后的密文和秘钥进行解密操作byte[] plainBytes = decryptCbcPadding(cipherBts, keyBts);// 将解密结果转换为字符串:srcData to String.return new String(plainBytes, CHARSET_UTF8);}/*** SM4算法的CBC模式解密.** @param cipherBytes 待加密密文.* @param sm4Key      Base64格式秘钥.* @return 解密后byte[]格式密文.* @throws Exception 可能异常.*/private static byte[] decryptCbcPadding(byte[] cipherBytes, byte[] sm4Key) throws Exception {Cipher cipher = generateSm4EcbCipher(SM4_NAME_ECB, Cipher.DECRYPT_MODE, sm4Key);return cipher.doFinal(cipherBytes);}/*** 针对错误的秘钥进行补齐或除余操作.** @param sm4Key Base64格式秘钥.* @return 补齐或除余后的结果.*/private static String sm4KeyPadding(String sm4Key) {String targetSm4Key;byte[] targetSm4KeyBts;if (null == sm4Key) {targetSm4Key = "";return targetSm4Key;}byte[] sm4KeyBytes = Base64.getDecoder().decode(sm4Key);// 若Key超长,则除去多余的内容.if (sm4KeyBytes.length > SM4_KEY_LENGTH) {targetSm4KeyBts = new byte[SM4_KEY_LENGTH];System.arraycopy(sm4KeyBytes, 0, targetSm4KeyBts, 0, SM4_KEY_LENGTH);}// 若Key较短,则补齐多余的内容.else if (sm4KeyBytes.length < SM4_KEY_LENGTH) {targetSm4KeyBts = new byte[SM4_KEY_LENGTH];System.arraycopy(sm4KeyBytes, 0, targetSm4KeyBts, 0, sm4KeyBytes.length);Arrays.fill(targetSm4KeyBts, sm4KeyBytes.length, SM4_KEY_LENGTH, (byte) 1);} else {targetSm4KeyBts = sm4KeyBytes;}// 以Base64格式返回Key.return Base64.getEncoder().encodeToString(targetSm4KeyBts);}/*** 生成SM4算法实例.** @param sm4Name 算法名称.* @param sm4Mode 加密模式.* @param sm4Key  秘钥内容.* @return SM4算法实例.* @throws Exception 可能异常.*/private static Cipher generateSm4EcbCipher(String sm4Name, int sm4Mode, byte[] sm4Key) throws Exception {Cipher cipher = Cipher.getInstance(sm4Name, BouncyCastleProvider.PROVIDER_NAME);Key secretKey = new SecretKeySpec(sm4Key, SM4_NAME);IvParameterSpec ivParameterSpec = new IvParameterSpec(CKEY.getBytes(StandardCharsets.UTF_8));cipher.init(sm4Mode, secretKey, ivParameterSpec);return cipher;}}

单元测试

package com.iscas.common.tools.core.security;import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;/*** @author zhuquanwen* @version 1.0* @date 2023/2/23 17:16*/
class Sm4UtilsTest {/*** 默认秘钥加密* */@Testvoid encrypt() throws Exception {String encrypt = Sm4Utils.encrypt("123456");System.out.println(encrypt);Assertions.assertNotNull(encrypt);}/*** 默认秘钥解密* */@Testvoid decrypt() throws Exception {String encrypt = Sm4Utils.encrypt("123456");String decrypt = Sm4Utils.decrypt(encrypt);Assertions.assertEquals(decrypt, "123456");}/*** 自定义秘钥加解密* */@Testvoid test3() throws Exception {String enKey = Sm4Utils.generateSm4Key();String encrypt = Sm4Utils.encrypt("123456", enKey);System.out.println(encrypt);String decrypt = Sm4Utils.decrypt(encrypt, enKey);Assertions.assertEquals(decrypt, "123456");}
}

Java各种方式加解密工具类相关推荐

  1. java aes 工具类_Java中的AES加解密工具类:AESUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...

  2. rsa java ao_RSA加解密工具类

    Java 实现 import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairG ...

  3. RSA加解密工具类(PKCS8公钥加密,PKCS1私钥解密)

    场景:如果项目上生成的秘钥,公钥是PKCS8格式,私钥却是PKCS1格式.需要在这种场景加解密的话可以直接使用下面工具类. 依赖 <dependency><groupId>or ...

  4. 阿里云专属KMS信封加解密工具类

    此工具类主要实现,字符串的加密,输出为Base64编码的字符串.字符串的解密,输入为Base64编码的字符串.工具类里的IV向量参数,需要用户自己保存,工具类中是默认写死在代码中的,并不规范.IV向量 ...

  5. 国密算法-SM4加解密工具类

    import cn.hutool.crypto.symmetric.SymmetricCrypto;/*** @author : chenfan* @className : SM4Utils* @da ...

  6. Java中的RSA加解密工具类:RSAUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt;import com.mirana.frame.utils.log.LogUtils; ...

  7. Java——DESUtil加解密工具类

    工具类代码如下: package util;import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto ...

  8. AES-128加解密工具类

    Java实现AES加密.解密 import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher; import java ...

  9. java des 加密工具的使用,Java中DES加密解密工具类的实现实例

    这篇文章主要介绍了Java实现的DES加密解密工具类,结合具体实例形式分析了Java实现的DES加密解密工具类定义与使用方法,需要的朋友可以参考下 本文实例讲述了Java实现的DES加密解密工具类.分 ...

最新文章

  1. 推荐6个绝赞良心工具,总有一些适合你!
  2. 传统数据中心穿上“云”外衣 任重而道远
  3. 开始学习python
  4. ITK:遍历图像的线
  5. 在Win7虚拟机下搭建Hadoop2.6.0伪分布式环境
  6. VS的TFS版本控制的使用总结
  7. HDU 1033 水题
  8. layui+strust2多文件上传
  9. 使用extundelete恢复测试liunx的删除文件
  10. spring读取jdbc(file方式)
  11. 【分享】一次单体架构改造成微服务架构的拆分实践
  12. wordpress后台出现404
  13. 【图像分割】基于区域的重叠椭圆拟合实现细胞分割附matlab代码
  14. 关于Qt6.2中的所有属性绑定
  15. java培训学习之Java工具的分享
  16. JS 两数相除取百分比%并保留两位小数
  17. 【2022年上半年信息系统管理综合知识】
  18. ¥符号在不同字体和设备上的显示
  19. ffmpeg 查询设备_ffmpeg 命令
  20. python飞机大战项目描述_飞机大战项目梳理(一)

热门文章

  1. 源码编译onnxruntime(打开onednn/oneapi)
  2. mapperscan扫描不到包问题
  3. 大数据电信客服-数据采集/消费(二)
  4. 【实锤了】UFO终极揭秘-NETFLIX
  5. rancher证书过期怎么办
  6. TinyOS操作系统介绍
  7. js将html字符串转化为html标签
  8. mmap详细解析及式例
  9. C++算法Day1之有趣的跳跃
  10. h264编码速度质量参数设置