Hunter0x7c7
2023-08-13 9cf7bde99b211c88edf9d64776d8c5b980c49deb
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.github.hunter0x7c7.sync.utils;
 
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
/**
 * AES加解密
 */
public class AesUtil {
    //填充类型
    public static final String AES_TYPE_CBC_PKCS5 = "AES/CBC/PKCS5Padding";// AES/CBC/PKCS7Padding
    public static final String AES_TYPE_ECB_PKCS5 = "AES/ECB/PKCS5Padding";
    public static final String AES_TYPE_ECB_PKCS7 = "AES/ECB/PKCS7Padding";
    //此类型 加密内容,密钥必须为16字节的倍数位,否则抛异常,需要字节补全再进行加密
    public static final String AES_TYPE_ECB_NO = "AES/ECB/NoPadding";
    //java 不支持ZeroPadding
    public static final String AES_TYPE_CBC_ZERO = "AES/CBC/ZeroPadding";
    //填充类型
    public static final String AES_DEF_TYPE = AES_TYPE_CBC_PKCS5;
 
    //编码方式
    public static final String CODE_TYPE = "UTF-8";//"GBK";
    //私钥
    private static final String AES_DEF_KEY = "110037d640411e09e76dd00e207d09f3";//AES固定格式为128/192/256 bits.即:16/24/32bytes。DES固定格式为128bits,即8bytes。
    //偏移量
    private static final String VIPARA = "1234567890123456";//CBC密钥默认偏移,可更改
 
    private static AesUtil mAesUtil;
 
    public static AesUtil getInstance() {
        if (mAesUtil == null) {
            synchronized (AesUtil.class) {
                if (mAesUtil == null) {
                    mAesUtil = new AesUtil();
                }
            }
        }
        return mAesUtil;
    }
 
    /**
     * 加密
     */
    public String encrypt(String plaintext) {
        return encrypt(plaintext, AES_DEF_KEY);
    }
 
    /**
     * 加密
     */
    public String encrypt(String plaintext, String privateKey) {
        return encrypt(AES_DEF_TYPE, plaintext, privateKey);
    }
 
    /**
     * 加密
     */
    public String encrypt(String type, String plaintext, String privateKey) {
        //加密方式: AES128(ECB/PKCS5Padding) + Base64, 私钥:privateKey
        try {
            if (plaintext != null && plaintext.length() > 0) {
                byte[] cipherText;
                if (type != null && privateKey != null) {
                    //两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
                    SecretKeySpec secretKey = new SecretKeySpec(privateKey.getBytes(), "AES");
                    byte[] bytes = plaintext.getBytes(CODE_TYPE);
                    if (AES_TYPE_CBC_PKCS5.equals(type)) {
                        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
                        cipherText = encrypt(type, secretKey, zeroIv, bytes);
                    } else {
                        cipherText = encrypt(type, secretKey, bytes);
                    }
                } else {
                    cipherText = null;
                }
                return Base64Encoder.encode(cipherText);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    /**
     * 解密
     */
    public String decrypt(String cipherTextBase64) {
        return decrypt(cipherTextBase64, AES_DEF_KEY);
    }
 
    /**
     * 解密
     */
    public String decrypt(String plaintext, String privateKey) {
        return decrypt(AES_DEF_TYPE, plaintext, privateKey);
    }
 
    /**
     * 解密
     */
    public String decrypt(String type, String plaintext, String privateKey) {
        try {
            if (plaintext != null && plaintext.length() > 0) {
                byte[] decrypt;
                if (type != null && privateKey != null) {
                    //两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
                    SecretKeySpec secretKey = new SecretKeySpec(privateKey.getBytes(), "AES");
                    byte[] bytes = Base64Decoder.decodeToBytes(plaintext);
                    if (AES_TYPE_CBC_PKCS5.equals(type)) {
                        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
                        decrypt = decrypt(type, secretKey, zeroIv, bytes);
                    } else {
                        decrypt = decrypt(type, secretKey, bytes);
                    }
                } else {
                    decrypt = null;
                }
                return decrypt != null ? new String(decrypt, CODE_TYPE) : null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    /**
     * 加密
     */
    private byte[] encrypt(String type, SecretKey key, byte[] msg) {
        try {
            Cipher c = Cipher.getInstance(type);
            c.init(Cipher.ENCRYPT_MODE, key);
            return c.doFinal(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
 
    /**
     * 加密
     */
    private byte[] encrypt(String type, SecretKey secretKey, IvParameterSpec params, byte[] msg) {
        try {
            //实例化加密类,参数为加密方式,要写全
            Cipher c = Cipher.getInstance(type);//PKCS5Padding比PKCS7Padding效率高,PKCS7Padding可支持IOS加解密
            //初始化,此方法可以采用三种方式,按加密算法要求来添加。
            // (1)无第三个参数
            // (2)第三个参数为SecureRandom random = new SecureRandom();中random对象,随机数。(AES不可采用这种方法)
            // (3)采用此代码中的IVParameterSpec
            //加密时使用:ENCRYPT_MODE;  解密时使用:DECRYPT_MODE;
            c.init(Cipher.ENCRYPT_MODE, secretKey, params);//CBC类型的可以在第三个参数传递偏移量zeroIv,ECB没有偏移量
            //加密操作,返回加密后的字节数组,然后需要编码。主要编解码方式有Base64, HEX, UUE,7bit等等。此处看服务器需要什么编码方式
            return c.doFinal(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
 
    /**
     * 解密
     */
    private byte[] decrypt(String type, SecretKey secretKey, IvParameterSpec params, byte[] cipherText) {
        try {
            Cipher c = Cipher.getInstance(type);
            c.init(Cipher.DECRYPT_MODE, secretKey, params);
            return c.doFinal(cipherText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    /**
     * 解密
     */
    private byte[] decrypt(String type, SecretKey secretKey, byte[] cipherText) {
        try {
            Cipher c = Cipher.getInstance(type);
            c.init(Cipher.DECRYPT_MODE, secretKey);
            return c.doFinal(cipherText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
}