当前位置:   article > 正文

Java各种方式加解密工具类_java加密解密工具类

java加密解密工具类


前言

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);
    }

}
  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151

单元测试:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * AES加解密测试类
 * @author zhuquanwen
 **/
public class AesUtilsTests {

    /**
     * 测试AES 默认加密
     * */
    @Test
    public void aesEncrpty() throws Exception {
        String sec = AesUtils.aesEncrypt("USER2");
        System.out.println(sec);
        Assertions.assertNotNull(sec);
    }

    /**
     *
     * 测试AES默认解密
     * */
    @Test
    public void aesDecrpty() throws Exception {
        String ori = AesUtils.aesDecrypt("Cg2jBQvUGJJUMfalO+HF5g==");
        Assertions.assertEquals("gfdx", ori);
    }

    /**
     * 测试AES 带KEY加密
    * */
    @Test
    public void aesEncrptyWithKey() throws Exception {
        String k = "6x9o67h5BO205Cfv";
        String sec = AesUtils.aesEncrypt("admin", k);
        Assertions.assertNotNull(sec);
    }

    /**
     * 测试AES 带KEY解密
     * */
    @Test
    public void aesDecrptyWithKey() throws Exception {
        String k = "6x9o67h5BO205Cfv";
        String ori = AesUtils.aesDecrypt("yij1zaxI6X10t7v6OpW7gw==", k);
        Assertions.assertEquals("admin", ori);
    }

}

  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

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;
    }

}
  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307

单元测试:

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 {

    @Test
    public void test1() throws Exception {
        String encrypt = DesUtils.encrypt("123456");
        System.out.println(encrypt);
        Assertions.assertNotNull(encrypt);
    }

    @Test
    public void test2() throws Exception {
        String decrypt = DesUtils.decrypt("yGj4sGSmFxs=");
        System.out.println(decrypt);
        Assertions.assertNotNull(decrypt);
    }

    /**
    * DES模式
    * */
    @Test
    public 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模式
     * */
    @Test
    public 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模式
     * */
    @Test
    public 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模式
     * */
    @Test
    public 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模式
     * */
    @Test
    public 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);
    }

}
  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

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 rounds
        if (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 word
            n = 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 word
            n = 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;
    }
}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534

单元测试:

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加解密
     * */
    @Test
    public 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);

    }
}

  • 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
  • 28
  • 29
  • 30
  • 31

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);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

引入依赖(gradle):

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

工具类:

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;
    }

    @NotNull
    private 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;
    }

}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309

单元测试:

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 {
    /**
     * 普通加密
     * */
    @Test
    public void MD51() throws NoSuchAlgorithmException {
        String sec = MD5Utils.md5("apply");
        Assertions.assertNotNull(sec);
    }
    /**
     * 加盐加密
     * */
    @Test
    public void MD52() throws NoSuchAlgorithmException {
        String sec = MD5Utils.saltMD5("admin");
        System.out.println(sec);
        Assertions.assertNotNull(sec);
    }
    /**
     * 加盐加密的校验
     * */
    @Test
    public void MD53() throws NoSuchAlgorithmException {
        boolean sec = MD5Utils.saltVerify("admin"
                ,"f2020e118a4aa8fd39a4560c79b16b30024fb29b64242b5e");
        Assertions.assertEquals(true, sec);
    }

    /**
     * hmac加密
     * */
    @Test
    public void MD54() {
        String iscas = MD5Utils.hmacMd5("iscas", "123456");
        System.out.println(iscas);
        Assertions.assertNotNull(iscas);
    }

    /**
     * hmac校验
     * */
    @Test
    public void MD55() {
        String data = MD5Utils.hmacMd5("iscas", "123456");
        System.out.println(data);
        boolean res = MD5Utils.hmacVerify("iscas", "123456", data);
        Assertions.assertTrue(res);
    }

    /**
     * 获取大文件MD5码
     * */
    @Test
    @Disabled
    public 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));
    }
}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

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);
    }
}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192

单元测试:

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 {

    @Test
    public 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();
        }
    }

}

  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

引入依赖(gradle):

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

工具类:

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);
        }
    }

    @NotNull
    private 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();
//    }
}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175

单元测试:

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 {

    @Test
    public void test() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String sha256Str = Sha256Utils.encrypt("123456");
        System.out.println(sha256Str);
    }


    @Test
    public void test2() {
        String iscas = Sha256Utils.hmacEncrypt("iscas", "123456");
        System.out.println(iscas);
        Assertions.assertNotNull(iscas);
    }

    @Test
    public void test3() {
        String sha = Sha256Utils.hmacEncrypt("iscas", "123456");
        System.out.println(sha);
        boolean res = Sha256Utils.hmacVerify("iscas", "123456", sha);
        Assertions.assertTrue(res);
    }
}

  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

引入依赖(gradle):

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

工具类:

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);
        // 调用hash
        byte[] 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();
//    }
}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398

单元测试:

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加密
     */
    @Test
    public void testEncode() {
        System.out.println(Sm3Utils.encrypt("123456"));
    }

    /**
     * 测试使用密钥hmac加密
     */
    @Test
    public void testEncode2() {
        System.out.println(Sm3Utils.hmacEncrypt("iscas", "123456"));
        System.out.println(Sm3Utils.hmacEncrypt("ISCAS", "123456"));
    }

    /**
     * 测试普通加密校验
     */
    @Test
    public void testVerify() {
        System.out.println(Sm3Utils.verify("123456", "207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb"));
    }

    /**
     * 测试HMAC加密校验
     */
    @Test
    public void testHmacVerify() {
        System.out.println(Sm3Utils.hmacVerify("iscas", "123456", "a0bc6c6ac39712c81f805c8a80407892b1006ee27a04c2b0a15fec84b5065225"));
    }

}
  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

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;
    }


}

  • 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
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289

单元测试

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 {

    /**
     * 默认秘钥加密
     * */
    @Test
    void encrypt() throws Exception {
        String encrypt = Sm4Utils.encrypt("123456");
        System.out.println(encrypt);
        Assertions.assertNotNull(encrypt);
    }

    /**
     * 默认秘钥解密
     * */
    @Test
    void decrypt() throws Exception {
        String encrypt = Sm4Utils.encrypt("123456");
        String decrypt = Sm4Utils.decrypt(encrypt);
        Assertions.assertEquals(decrypt, "123456");
    }

    /**
     * 自定义秘钥加解密
     * */
    @Test
    void 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");
    }
}
  • 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
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/441328
推荐阅读
相关标签
  

闽ICP备14008679号