(...);
75 | }
76 |
77 | #忽略警告
78 | -ignorewarnings
79 | #保证是独立的jar,没有任何项目引用,如果不写就会认为我们所有的代码是无用的,从而把所有的代码压缩掉,导出一个空的jar
80 | -dontshrink
81 | #保护泛型
82 | -keepattributes Signature
83 | #代码迭代优化的次数,默认5
84 | -optimizationpasses 5
85 | #混淆时不会产生形形色色的类名
86 | -dontusemixedcaseclassnames
87 |
88 | # 不混淆某个类(使用者可以看到类名)
89 | -keep class cn.mtjsoft.lib_encryption.** {
90 | public *;
91 | }
92 |
93 | # 不混淆某个类中以 public 开始的方法(使用者可以看到该方法)
94 | -keepclassmembers class cn.mtjsoft.lib_encryption.** {
95 | public *;
96 | }
--------------------------------------------------------------------------------
/lib_encryption/src/androidTest/java/cn/mtjsoft/lib_encryption/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("cn.mtjsoft.lib_encryption.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/lib_encryption/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/AES/AESUtil.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.AES;
2 |
3 | import java.security.NoSuchAlgorithmException;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.KeyGenerator;
7 | import javax.crypto.SecretKey;
8 | import javax.crypto.spec.IvParameterSpec;
9 | import javax.crypto.spec.SecretKeySpec;
10 |
11 | /**
12 | * @author mtj
13 | * @date 2021/8/6
14 | * @desc 对称加密,加解密的密钥需要保持一致
15 | * @email mtjsoft3@gmail.com
16 | */
17 | public class AESUtil {
18 | /**
19 | * 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
20 | * AES/CBC/NoPadding 16 不支持
21 | * AES/CBC/PKCS5Padding 32 16
22 | * AES/CBC/ISO10126Padding 32 16
23 | * AES/CFB/NoPadding 16 原始数据长度
24 | * AES/CFB/PKCS5Padding 32 16
25 | * AES/CFB/ISO10126Padding 32 16
26 | * AES/ECB/NoPadding 16 不支持
27 | * AES/ECB/PKCS5Padding 32 16
28 | * AES/ECB/ISO10126Padding 32 16
29 | * AES/OFB/NoPadding 16 原始数据长度
30 | * AES/OFB/PKCS5Padding 32 16
31 | * AES/OFB/ISO10126Padding 32 16
32 | * AES/PCBC/NoPadding 16 不支持
33 | * AES/PCBC/PKCS5Padding 32 16
34 | * AES/PCBC/ISO10126Padding 32 16
35 | */
36 | private static final String AES = "AES";
37 |
38 | private static final String AES_ECB_NO_PADDING = "AES/ECB/NoPadding";
39 |
40 | private static final String AES_CBC_NO_PADDING = "AES/CBC/NoPadding";
41 |
42 | private static final String AES_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
43 |
44 | /**
45 | * 生成秘钥
46 | */
47 | public static byte[] generateKey() {
48 | KeyGenerator keyGen = null;
49 | try {
50 | // 秘钥生成器
51 | keyGen = KeyGenerator.getInstance(AES);
52 | } catch (NoSuchAlgorithmException e) {
53 | e.printStackTrace();
54 | }
55 | if (keyGen != null) {
56 | // 初始秘钥生成器
57 | keyGen.init(128);
58 | // 生成秘钥
59 | SecretKey secretKey = keyGen.generateKey();
60 | // 获取秘钥字节数组
61 | return secretKey.getEncoded();
62 | }
63 | return null;
64 | }
65 |
66 | /**
67 | * 生成秘钥
68 | */
69 | public static byte[] generateKey256() {
70 | KeyGenerator keyGen = null;
71 | try {
72 | // 秘钥生成器
73 | keyGen = KeyGenerator.getInstance(AES);
74 | } catch (NoSuchAlgorithmException e) {
75 | e.printStackTrace();
76 | }
77 | if (keyGen != null) {
78 | // 初始秘钥生成器
79 | keyGen.init(256);
80 | // 生成秘钥
81 | SecretKey secretKey = keyGen.generateKey();
82 | // 获取秘钥字节数组
83 | return secretKey.getEncoded();
84 | }
85 | return null;
86 | }
87 |
88 | /**
89 | * 加密
90 | */
91 | public static byte[] encrypt(byte[] data, byte[] key) {
92 | return init(data, key, Cipher.ENCRYPT_MODE);
93 | }
94 |
95 | /**
96 | * 解密
97 | */
98 | public static byte[] decrypt(byte[] data, byte[] key) {
99 | return init(data, key, Cipher.DECRYPT_MODE);
100 | }
101 |
102 | private static byte[] init(byte[] data, byte[] key, int decryptMode) {
103 | try {
104 | // 恢复秘钥
105 | SecretKey secretKey = new SecretKeySpec(key, AES);
106 | // 对Cipher初始化,加密模式
107 | Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5);
108 | //CBC模式
109 | // 对Cipher初始化,加密模式
110 | cipher.init(decryptMode, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
111 | // 解密数据
112 | return cipher.doFinal(data);
113 | } catch (Exception e) {
114 | e.printStackTrace();
115 | }
116 | return null;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/BASE64/Base64Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.BASE64;
2 |
3 | /**
4 | * @author mtj
5 | * @date 2021/8/6
6 | * @desc
7 | * @email mtjsoft3@gmail.com
8 | */
9 | public class Base64Util {
10 |
11 | private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
12 |
13 | private static final int[] TO_INT = new int[128];
14 |
15 | static {
16 | for (int i = 0; i < ALPHABET.length; i++) {
17 | TO_INT[ALPHABET[i]] = i;
18 | }
19 | }
20 |
21 | /**
22 | * 编码
23 | */
24 | public static byte[] encodeBy(byte[] buff) {
25 | return encode(buff).getBytes();
26 | }
27 |
28 | /**
29 | * 编码
30 | * Translates the specified byte array into Base64 string.
31 | *
32 | * @param buf the byte array (not null)
33 | * @return the translated Base64 string (not null)
34 | */
35 | public static String encode(byte[] buf) {
36 | int size = buf.length;
37 | char[] ar = new char[((size + 2) / 3) * 4];
38 | int a = 0;
39 | int i = 0;
40 | while (i < size) {
41 | byte b0 = buf[i++];
42 | byte b1 = (i < size) ? buf[i++] : 0;
43 | byte b2 = (i < size) ? buf[i++] : 0;
44 | int mask = 0x3F;
45 | ar[a++] = ALPHABET[(b0 >> 2) & mask];
46 | ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
47 | ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
48 | ar[a++] = ALPHABET[b2 & mask];
49 | }
50 | switch (size % 3) {
51 | case 1:
52 | ar[--a] = '=';
53 | case 2:
54 | ar[--a] = '=';
55 | break;
56 | default:
57 | break;
58 | }
59 | return new String(ar);
60 | }
61 |
62 | /**
63 | * 解码
64 | * Translates the specified Base64 string into a byte array.
65 | *
66 | * @param s the Base64 string (not null)
67 | * @return the byte array (not null)
68 | */
69 | public static byte[] decode(String s) {
70 | int delta = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0;
71 | byte[] buffer = new byte[s.length() * 3 / 4 - delta];
72 | int mask = 0xFF;
73 | int index = 0;
74 | for (int i = 0; i < s.length(); i += 4) {
75 | int c0 = TO_INT[s.charAt(i)];
76 | int c1 = TO_INT[s.charAt(i + 1)];
77 | buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
78 | if (index >= buffer.length) {
79 | return buffer;
80 | }
81 | int c2 = TO_INT[s.charAt(i + 2)];
82 | buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
83 | if (index >= buffer.length) {
84 | return buffer;
85 | }
86 | int c3 = TO_INT[s.charAt(i + 3)];
87 | buffer[index++] = (byte) (((c2 << 6) | c3) & mask);
88 | }
89 | return buffer;
90 | }
91 |
92 | /**
93 | * 判断是否是Base64加密后的数据
94 | */
95 | public static boolean isBase64Decode(String message) {
96 | try {
97 | if (!message.equals(encode(decode(message)))) {
98 | return false;
99 | }
100 | } catch (Exception e) {
101 | return false;
102 | }
103 | return true;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/MD5/MD5Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.MD5;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.IOException;
6 | import java.nio.MappedByteBuffer;
7 | import java.nio.channels.FileChannel;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 |
11 | import cn.mtjsoft.lib_encryption.utils.Util;
12 |
13 | /**
14 | * @author mtj
15 | * @date 2021/8/6
16 | * @desc 消息摘要算法5, 单向加密算法,是不可逆的一种的加密方式
17 | * @email mtjsoft3@gmail.com
18 | *
19 | * MD5加密有哪些特点:
20 | *
21 | * 压缩性:任意长度的数据,算出的MD5值长度都是固定的。
22 | *
23 | * 容易计算:从原数据计算出MD5值很容易。
24 | *
25 | * 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
26 | *
27 | * 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
28 | *
29 | * MD5应用场景:
30 | *
31 | * 一致性验证
32 | *
33 | * 数字签名
34 | *
35 | * 安全访问认证
36 | */
37 | public class MD5Util {
38 | /**
39 | * 计算字符串MD5值
40 | */
41 | public static String stringMD5(String input) {
42 | try {
43 | // 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)
44 | MessageDigest messageDigest = MessageDigest.getInstance("MD5");
45 | // 输入的字符串转换成字节数组
46 | byte[] inputByteArray = input.getBytes();
47 | // inputByteArray是输入字符串转换得到的字节数组
48 | messageDigest.update(inputByteArray);
49 | // 转换并返回结果,也是字节数组,包含16个元素
50 | byte[] resultByteArray = messageDigest.digest();
51 | // 字符数组转换成字符串返回
52 | return Util.byte2HexStr(resultByteArray);
53 | } catch (NoSuchAlgorithmException e) {
54 | return "";
55 | }
56 | }
57 |
58 | public static String stringMD5(byte[] inputByteArray) {
59 | try {
60 | // 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)
61 | MessageDigest messageDigest = MessageDigest.getInstance("MD5");
62 | // inputByteArray是输入字符串转换得到的字节数组
63 | messageDigest.update(inputByteArray);
64 | // 转换并返回结果,也是字节数组,包含16个元素
65 | byte[] resultByteArray = messageDigest.digest();
66 | // 字符数组转换成字符串返回
67 | return Util.byte2HexStr(resultByteArray);
68 | } catch (NoSuchAlgorithmException e) {
69 | return "";
70 | }
71 | }
72 |
73 | /**
74 | * 计算文件MD5值
75 | */
76 | public static String getMd5ByFile(File file) {
77 | String result = "";
78 | if (!file.isFile()) {
79 | return result;
80 | }
81 | MessageDigest digest = null;
82 | FileInputStream in = null;
83 | byte[] buffer = new byte[1024];
84 | int len;
85 | try {
86 | digest = MessageDigest.getInstance("MD5");
87 | in = new FileInputStream(file);
88 | while ((len = in.read(buffer, 0, 1024)) != -1) {
89 | digest.update(buffer, 0, len);
90 | }
91 | in.close();
92 | result = Util.byte2HexStr(digest.digest());
93 | } catch (Exception e) {
94 | e.printStackTrace();
95 | result = "";
96 | }
97 | return result;
98 | }
99 |
100 | /**
101 | * 计算文件MD5值
102 | *
103 | * 采用nio的方式
104 | */
105 | public static String getMd5ByFileNio(File file) {
106 | String result = "";
107 | if (!file.isFile()) {
108 | return result;
109 | }
110 | FileInputStream in = null;
111 | try {
112 | in = new FileInputStream(file);
113 | MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
114 | MessageDigest md5 = MessageDigest.getInstance("MD5");
115 | md5.update(byteBuffer);
116 | result = Util.byte2HexStr(md5.digest());
117 | } catch (Exception e) {
118 | e.printStackTrace();
119 | } finally {
120 | if (null != in) {
121 | try {
122 | in.close();
123 | } catch (IOException e) {
124 | e.printStackTrace();
125 | }
126 | }
127 | }
128 | return result;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/RSA/RSAUtil.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.RSA;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.security.KeyFactory;
5 | import java.security.KeyPair;
6 | import java.security.KeyPairGenerator;
7 | import java.security.NoSuchAlgorithmException;
8 | import java.security.PrivateKey;
9 | import java.security.PublicKey;
10 | import java.security.Signature;
11 | import java.security.spec.PKCS8EncodedKeySpec;
12 | import java.security.spec.X509EncodedKeySpec;
13 |
14 | import javax.crypto.Cipher;
15 |
16 | /**
17 | * @author mtj
18 | * @date 2021/8/6
19 | * @desc 非对称加密算法。
20 | *
21 | * 加密:防止消息泄露
22 | * 签名:防止消息篡改
23 | * (总结:公钥加密、私钥解密、私钥签名、公钥验签)
24 | * @email mtjsoft3@gmail.com
25 | */
26 | public class RSAUtil {
27 | private static final String RSA = "RSA";
28 |
29 | /**
30 | * 填充方式
31 | */
32 | private static final String RSA_NO_PADDING = "RSA/ECB/NoPadding";
33 |
34 | private static final String RSA_PADDING = "RSA/ECB/PKCS1Padding";
35 |
36 | /**
37 | * 签名方式
38 | */
39 | private static final String SIGN_MD5withRSA = "MD5withRSA";
40 |
41 | private static final String SIGN_SHA256WithRSA = "SHA256WithRSA";
42 |
43 | /**
44 | * 密钥长度
45 | */
46 | private static final int DEFAULT_KEY_SIZE = 2048;
47 |
48 | /**
49 | * 待解密的字节数不能超过密钥的长度值除以 8 (即:KeySize / 8 )
50 | */
51 | private static final int MAX_DECRYPT_BLOCK = DEFAULT_KEY_SIZE / 8;
52 |
53 | /**
54 | * 待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:KeySize / 8 - 11)
55 | */
56 | private static final int MAX_ENCRYPT_BLOCK = MAX_DECRYPT_BLOCK - 11;
57 |
58 | /**
59 | * 随机生成RSA密钥对
60 | *
61 | * 密钥长度,范围:512~2048
62 | * 一般1024 或 2048
63 | */
64 | public static KeyPair generateRSAKeyPair() {
65 | try {
66 | KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
67 | kpg.initialize(DEFAULT_KEY_SIZE);
68 | return kpg.genKeyPair();
69 | } catch (NoSuchAlgorithmException e) {
70 | e.printStackTrace();
71 | return null;
72 | }
73 | }
74 |
75 | /**
76 | * 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法
77 | *
78 | * @param publicKeys 公钥byte[],(publicKey.getEncoded())
79 | */
80 | public static PublicKey getPublicKey(byte[] publicKeys) {
81 | try {
82 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeys);
83 | KeyFactory keyFactory = KeyFactory.getInstance(RSA);
84 | return keyFactory.generatePublic(keySpec);
85 | } catch (Exception e) {
86 | e.printStackTrace();
87 | }
88 | return null;
89 | }
90 |
91 | /**
92 | * 通过私钥byte[]将私钥还原,适用于RSA算法
93 | *
94 | * @param privateKeys 私钥byte[],(privateKey.getEncoded())
95 | */
96 | public static PrivateKey getPrivateKey(byte[] privateKeys) {
97 | try {
98 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeys);
99 | KeyFactory keyFactory = KeyFactory.getInstance(RSA);
100 | return keyFactory.generatePrivate(keySpec);
101 | } catch (Exception e) {
102 | e.printStackTrace();
103 | }
104 | return null;
105 | }
106 |
107 | /**
108 | * 用公钥进行加密
109 | *
110 | * @param data 原文
111 | */
112 | public static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey) {
113 | // 加密数据
114 | try {
115 | Cipher cipher = Cipher.getInstance(RSA_PADDING);
116 | // 编码前设定编码方式及密钥
117 | cipher.init(Cipher.ENCRYPT_MODE, publicKey);
118 | // 传入编码数据并返回编码结果
119 | return segmented(data, cipher, true);
120 | } catch (Exception e) {
121 | e.printStackTrace();
122 | return null;
123 | }
124 | }
125 |
126 | /**
127 | * 用私钥进行加密
128 | *
129 | * @param data 原文
130 | */
131 | public static byte[] encryptByPrivateKey(byte[] data, PrivateKey privateKey) {
132 | // 加密数据
133 | try {
134 | Cipher cipher = Cipher.getInstance(RSA_PADDING);
135 | // 编码前设定编码方式及密钥
136 | cipher.init(Cipher.ENCRYPT_MODE, privateKey);
137 | // 传入编码数据并返回编码结果
138 | return segmented(data, cipher, true);
139 | } catch (Exception e) {
140 | e.printStackTrace();
141 | return null;
142 | }
143 | }
144 |
145 | /**
146 | * 用公钥解密
147 | *
148 | * @param encryptedData 经过加密数据
149 | * @param publicKey 公钥
150 | */
151 | public static byte[] decryptByPublicKeyKey(byte[] encryptedData, PublicKey publicKey) {
152 | try {
153 | Cipher cipher = Cipher.getInstance(RSA_PADDING);
154 | cipher.init(Cipher.DECRYPT_MODE, publicKey);
155 | return segmented(encryptedData, cipher, false);
156 | } catch (Exception e) {
157 | return null;
158 | }
159 | }
160 |
161 | /**
162 | * 用私钥解密
163 | *
164 | * @param encryptedData 经过加密数据
165 | * @param privateKey 私钥
166 | */
167 | public static byte[] decryptByPrivateKey(byte[] encryptedData, PrivateKey privateKey) {
168 | try {
169 | Cipher cipher = Cipher.getInstance(RSA_PADDING);
170 | cipher.init(Cipher.DECRYPT_MODE, privateKey);
171 | return segmented(encryptedData, cipher, false);
172 | } catch (Exception e) {
173 | return null;
174 | }
175 | }
176 |
177 | /**
178 | * SHA256
179 | * 用私钥签名
180 | *
181 | * @param bytes 待签名数据
182 | * @param privateKey 私钥
183 | * @return 结果
184 | */
185 | public static byte[] signWithSHA256(byte[] bytes, PrivateKey privateKey) throws Exception {
186 | Signature signature = Signature.getInstance(SIGN_SHA256WithRSA);
187 | signature.initSign(privateKey);
188 | signature.update(bytes);
189 | return signature.sign();
190 | }
191 |
192 | /**
193 | * SHA256
194 | * 用公钥验签
195 | *
196 | * @param srcData 原始数据
197 | * @param signBytes 签名数据
198 | * @param publicKey 公钥
199 | * @return 结果
200 | */
201 | public static boolean verifySignWithSHA256(byte[] srcData, byte[] signBytes, PublicKey publicKey) throws Exception {
202 | Signature signature = Signature.getInstance(SIGN_SHA256WithRSA);
203 | signature.initVerify(publicKey);
204 | signature.update(srcData);
205 | return signature.verify(signBytes);
206 | }
207 |
208 | /**
209 | * MD5
210 | * 用私钥签名
211 | *
212 | * @param bytes 待签名数据
213 | * @param privateKey 私钥
214 | * @return 结果
215 | */
216 | public static byte[] signWithMD5(byte[] bytes, PrivateKey privateKey) throws Exception {
217 | Signature signature = Signature.getInstance(SIGN_MD5withRSA);
218 | signature.initSign(privateKey);
219 | signature.update(bytes);
220 | return signature.sign();
221 | }
222 |
223 | /**
224 | * MD5
225 | * 用公钥验签
226 | *
227 | * @param srcData 原始数据
228 | * @param signBytes 签名数据
229 | * @param publicKey 公钥
230 | * @return 结果
231 | */
232 | public static boolean verifySignWithMD5(byte[] srcData, byte[] signBytes, PublicKey publicKey) throws Exception {
233 | Signature signature = Signature.getInstance(SIGN_MD5withRSA);
234 | signature.initVerify(publicKey);
235 | signature.update(srcData);
236 | return signature.verify(signBytes);
237 | }
238 |
239 | /**
240 | * 分段加解密
241 | *
242 | * @param data 待加解密的数据
243 | * @param isEncrypt 是否是加密,否则是解密
244 | */
245 | private static byte[] segmented(byte[] data, Cipher cipher, boolean isEncrypt) throws Exception {
246 | int inputLen = data.length;
247 | // 不够分段加密条件,直接进行一次性加密返回
248 | if (isEncrypt && inputLen <= MAX_ENCRYPT_BLOCK) {
249 | return cipher.doFinal(data);
250 | }
251 | // 不够分段解密条件,直接进行一次性解密返回
252 | if (!isEncrypt && inputLen <= MAX_DECRYPT_BLOCK) {
253 | return cipher.doFinal(data);
254 | }
255 | ByteArrayOutputStream out = new ByteArrayOutputStream();
256 | int offset = 0;
257 | byte[] cache;
258 | int i = 0;
259 | int maxLen = isEncrypt ? MAX_ENCRYPT_BLOCK : MAX_DECRYPT_BLOCK;
260 | // 对数据分段加密
261 | while (inputLen - offset > 0) {
262 | if (inputLen - offset > maxLen) {
263 | cache = cipher.doFinal(data, offset, maxLen);
264 | } else {
265 | cache = cipher.doFinal(data, offset, inputLen - offset);
266 | }
267 | out.write(cache, 0, cache.length);
268 | i++;
269 | offset = i * maxLen;
270 | }
271 | out.close();
272 | return out.toByteArray();
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SHA/SHAUtil.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SHA;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.IOException;
6 | import java.nio.MappedByteBuffer;
7 | import java.nio.channels.FileChannel;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 |
11 | import cn.mtjsoft.lib_encryption.utils.Util;
12 |
13 | /**
14 | * @author mtj
15 | * @date 2021/8/6
16 | * @desc
17 | * @email mtjsoft3@gmail.com
18 | *
19 | * SHA加密优点:
20 | *
21 | * 由于SHA也是有MD4演变过来的,所以其优点与MD5大致一样
22 | *
23 | * 压缩性:任意长度的数据,算出的SHA值长度都是固定的。
24 | *
25 | * 容易计算:从原数据计算出SHA值很容易。
26 | *
27 | * 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的SHA值都有很大区别。
28 | *
29 | * 强抗碰撞:已知原数据和其SHA值,想找到一个具有相同SHA值的数据(即伪造数据)是非常困难的。
30 | *
31 | * SHA应用场景:
32 | *
33 | * 一致性验证
34 | *
35 | * 数字签名
36 | *
37 | * 安全访问认证
38 | */
39 | public class SHAUtil {
40 |
41 | public static final String SHA1 = "SHA-1";
42 |
43 | public static final String SHA256 = "SHA-256";
44 |
45 | /**
46 | * 计算字符串SHA1值
47 | */
48 | public static String stringSHA(String input, String shaType) {
49 | try {
50 | // 拿到一个SHA1
51 | MessageDigest messageDigest = MessageDigest.getInstance(shaType);
52 | // 输入的字符串转换成字节数组
53 | byte[] inputByteArray = input.getBytes();
54 | // inputByteArray是输入字符串转换得到的字节数组
55 | messageDigest.update(inputByteArray);
56 | // 转换并返回结果,也是字节数组,包含16个元素
57 | byte[] resultByteArray = messageDigest.digest();
58 | // 字符数组转换成字符串返回
59 | return Util.byte2HexStr(resultByteArray);
60 | } catch (NoSuchAlgorithmException e) {
61 | return "";
62 | }
63 | }
64 |
65 | public static String stringSHA(byte[] inputByteArray, String shaType) {
66 | try {
67 | // 拿到一个SHA1
68 | MessageDigest messageDigest = MessageDigest.getInstance(shaType);
69 | // inputByteArray是输入字符串转换得到的字节数组
70 | messageDigest.update(inputByteArray);
71 | // 转换并返回结果,也是字节数组,包含16个元素
72 | byte[] resultByteArray = messageDigest.digest();
73 | // 字符数组转换成字符串返回
74 | return Util.byte2HexStr(resultByteArray);
75 | } catch (NoSuchAlgorithmException e) {
76 | return "";
77 | }
78 | }
79 |
80 | /**
81 | * 计算文件SHA1值
82 | */
83 | public static String getSHAByFile(File file, String shaType) {
84 | String result = "";
85 | if (!file.isFile()) {
86 | return result;
87 | }
88 | MessageDigest digest = null;
89 | FileInputStream in = null;
90 | byte[] buffer = new byte[1024];
91 | int len;
92 | try {
93 | digest = MessageDigest.getInstance(shaType);
94 | in = new FileInputStream(file);
95 | while ((len = in.read(buffer, 0, 1024)) != -1) {
96 | digest.update(buffer, 0, len);
97 | }
98 | in.close();
99 | result = Util.byte2HexStr(digest.digest());
100 | } catch (Exception e) {
101 | e.printStackTrace();
102 | result = "";
103 | }
104 | return result;
105 | }
106 |
107 | /**
108 | * 计算文件SHA1值
109 | *
110 | * 采用nio的方式
111 | */
112 | public static String getSHAByFileNio(File file, String shaType) {
113 | String result = "";
114 | if (!file.isFile()) {
115 | return result;
116 | }
117 | FileInputStream in = null;
118 | try {
119 | in = new FileInputStream(file);
120 | MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
121 | MessageDigest md5 = MessageDigest.getInstance(shaType);
122 | md5.update(byteBuffer);
123 | result = Util.byte2HexStr(md5.digest());
124 | } catch (Exception e) {
125 | e.printStackTrace();
126 | } finally {
127 | if (null != in) {
128 | try {
129 | in.close();
130 | } catch (IOException e) {
131 | e.printStackTrace();
132 | }
133 | }
134 | }
135 | return result;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SM2/SM2.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SM2;
2 |
3 | import org.bouncycastle.asn1.x9.ECNamedCurveTable;
4 | import org.bouncycastle.asn1.x9.X9ECParameters;
5 | import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
6 | import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
7 | import org.bouncycastle.crypto.params.ECDomainParameters;
8 | import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
9 | import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
10 | import org.bouncycastle.crypto.params.ECPublicKeyParameters;
11 | import org.bouncycastle.math.ec.ECCurve;
12 | import org.bouncycastle.math.ec.ECPoint;
13 | import org.bouncycastle.math.ec.FixedPointCombMultiplier;
14 | import org.bouncycastle.math.ec.WNafUtil;
15 | import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
16 |
17 | import java.math.BigInteger;
18 | import java.security.SecureRandom;
19 |
20 | /**
21 | * @author mtj
22 | * @date 2021/8/12
23 | * @desc
24 | * @email mtjsoft3@gmail.com
25 | */
26 | class SM2 {
27 | private final ECCurve mCurve;
28 |
29 | private final ECDomainParameters mDomainParams;
30 |
31 | private final ECKeyPairGenerator mKeyPairGenerator;
32 |
33 | private final ECPoint mECPoint_G;
34 |
35 | private SM2() {
36 | X9ECParameters x9 = ECNamedCurveTable.getByName("sm2p256v1");
37 | this.mCurve = x9.getCurve();
38 | this.mECPoint_G = x9.getG();
39 | this.mDomainParams = new ECDomainParameters(x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
40 | ECKeyGenerationParameters ecc_ecgenparam = new ECKeyGenerationParameters(this.mDomainParams, new SecureRandom());
41 | this.mKeyPairGenerator = new ECKeyPairGenerator();
42 | this.mKeyPairGenerator.init(ecc_ecgenparam);
43 | }
44 |
45 | static SM2 Instance() {
46 | return Holder.INSTANCE;
47 | }
48 |
49 | ECPublicKeyParameters getPublicKeyParameters(byte[] publicKey) {
50 | if (publicKey.length == 64) {
51 | publicKey = ByteUtils.concatenate(new byte[] { SM2Util.MODE_NO_COMPRESS }, publicKey);
52 | }
53 |
54 | ECPoint q = this.mCurve.decodePoint(publicKey);
55 | return new ECPublicKeyParameters(q, this.mDomainParams);
56 | }
57 |
58 | ECPrivateKeyParameters getPrivateKeyParameters(byte[] privateKey) {
59 | BigInteger d = new BigInteger(1, privateKey);
60 | return new ECPrivateKeyParameters(d, this.mDomainParams);
61 | }
62 |
63 | AsymmetricCipherKeyPair generateKeyPair() {
64 | return this.mKeyPairGenerator.generateKeyPair();
65 | }
66 |
67 | byte[] getPublicKeyFromPrivateKey(byte[] privateKey) {
68 | BigInteger d = new BigInteger(1, privateKey);
69 | ECPoint Q = (new FixedPointCombMultiplier()).multiply(this.mECPoint_G, d);
70 | byte[] publicKeyEncoded = Q.getEncoded(false);
71 | if (publicKeyEncoded.length == 65) {
72 | publicKeyEncoded = ByteUtils.subArray(publicKeyEncoded, 1, publicKeyEncoded.length);
73 | }
74 |
75 | return publicKeyEncoded;
76 | }
77 |
78 | boolean isValidPrivateKey(byte[] privateKey) {
79 | BigInteger d = new BigInteger(1, privateKey);
80 | BigInteger n = this.mDomainParams.getN();
81 | return d.compareTo(BigInteger.ONE) >= 0 && d.compareTo(n) < 0;
82 | }
83 |
84 | private static final class Holder {
85 | private static final SM2 INSTANCE = new SM2();
86 |
87 | private Holder() {
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SM2/SM2Signer.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SM2;
2 |
3 | import org.bouncycastle.crypto.CipherParameters;
4 | import org.bouncycastle.crypto.CryptoException;
5 | import org.bouncycastle.crypto.CryptoServicesRegistrar;
6 | import org.bouncycastle.crypto.Digest;
7 | import org.bouncycastle.crypto.Signer;
8 | import org.bouncycastle.crypto.digests.SM3Digest;
9 | import org.bouncycastle.crypto.params.ECDomainParameters;
10 | import org.bouncycastle.crypto.params.ECKeyParameters;
11 | import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
12 | import org.bouncycastle.crypto.params.ECPublicKeyParameters;
13 | import org.bouncycastle.crypto.params.ParametersWithID;
14 | import org.bouncycastle.crypto.params.ParametersWithRandom;
15 | import org.bouncycastle.crypto.signers.DSAEncoding;
16 | import org.bouncycastle.crypto.signers.DSAKCalculator;
17 | import org.bouncycastle.crypto.signers.RandomDSAKCalculator;
18 | import org.bouncycastle.crypto.signers.StandardDSAEncoding;
19 | import org.bouncycastle.math.ec.ECAlgorithms;
20 | import org.bouncycastle.math.ec.ECConstants;
21 | import org.bouncycastle.math.ec.ECFieldElement;
22 | import org.bouncycastle.math.ec.ECMultiplier;
23 | import org.bouncycastle.math.ec.ECPoint;
24 | import org.bouncycastle.math.ec.FixedPointCombMultiplier;
25 | import org.bouncycastle.util.encoders.Hex;
26 |
27 | import java.math.BigInteger;
28 |
29 | /**
30 | * @author mtj
31 | * @date 2021/8/12
32 | * @desc
33 | * @email mtjsoft3@gmail.com
34 | */
35 | class SM2Signer implements Signer, ECConstants {
36 | private final DSAKCalculator kCalculator;
37 | private final Digest digest;
38 | private final DSAEncoding encoding;
39 | private ECDomainParameters ecParams;
40 | private ECPoint pubPoint;
41 | private ECKeyParameters ecKey;
42 |
43 | public SM2Signer() {
44 | this(StandardDSAEncoding.INSTANCE, new SM3Digest());
45 | }
46 |
47 | public SM2Signer(Digest digest) {
48 | this(StandardDSAEncoding.INSTANCE, digest);
49 | }
50 |
51 | public SM2Signer(DSAEncoding encoding) {
52 | this.kCalculator = new RandomDSAKCalculator();
53 | this.encoding = encoding;
54 | this.digest = new SM3Digest();
55 | }
56 |
57 | public SM2Signer(DSAEncoding encoding, Digest digest) {
58 | this.kCalculator = new RandomDSAKCalculator();
59 | this.encoding = encoding;
60 | this.digest = digest;
61 | }
62 |
63 | @Override
64 | public void init(boolean forSigning, CipherParameters param) {
65 | CipherParameters baseParam;
66 | byte[] userID;
67 | if (param instanceof ParametersWithID) {
68 | baseParam = ((ParametersWithID)param).getParameters();
69 | userID = ((ParametersWithID)param).getID();
70 | if (userID.length >= 8192) {
71 | throw new IllegalArgumentException("SM2 user ID must be less than 2^16 bits long");
72 | }
73 | } else {
74 | baseParam = param;
75 | userID = Hex.decodeStrict("31323334353637383132333435363738");
76 | }
77 |
78 | if (forSigning) {
79 | if (baseParam instanceof ParametersWithRandom) {
80 | ParametersWithRandom rParam = (ParametersWithRandom)baseParam;
81 | this.ecKey = (ECKeyParameters)rParam.getParameters();
82 | this.ecParams = this.ecKey.getParameters();
83 | this.kCalculator.init(this.ecParams.getN(), rParam.getRandom());
84 | } else {
85 | this.ecKey = (ECKeyParameters)baseParam;
86 | this.ecParams = this.ecKey.getParameters();
87 | this.kCalculator.init(this.ecParams.getN(), CryptoServicesRegistrar.getSecureRandom());
88 | }
89 |
90 | this.pubPoint = this.createBasePointMultiplier().multiply(this.ecParams.getG(), ((ECPrivateKeyParameters)this.ecKey).getD()).normalize();
91 | } else {
92 | this.ecKey = (ECKeyParameters)baseParam;
93 | this.ecParams = this.ecKey.getParameters();
94 | this.pubPoint = ((ECPublicKeyParameters)this.ecKey).getQ();
95 | }
96 |
97 | }
98 |
99 | @Override
100 | public void update(byte b) {
101 | this.digest.update(b);
102 | }
103 |
104 | @Override
105 | public void update(byte[] in, int off, int len) {
106 | this.digest.update(in, off, len);
107 | }
108 |
109 | @Override
110 | public boolean verifySignature(byte[] signature) {
111 | try {
112 | BigInteger[] rs = this.encoding.decode(this.ecParams.getN(), signature);
113 | return this.verifySignature(rs[0], rs[1]);
114 | } catch (Exception var3) {
115 | return false;
116 | }
117 | }
118 |
119 | @Override
120 | public void reset() {
121 | this.digest.reset();
122 | }
123 |
124 | @Override
125 | public byte[] generateSignature() throws CryptoException {
126 | byte[] eHash = this.digestDoFinal();
127 | BigInteger n = this.ecParams.getN();
128 | BigInteger e = this.calculateE(n, eHash);
129 | BigInteger d = ((ECPrivateKeyParameters)this.ecKey).getD();
130 | ECMultiplier basePointMultiplier = this.createBasePointMultiplier();
131 |
132 | while(true) {
133 | BigInteger r;
134 | BigInteger k;
135 | do {
136 | k = this.kCalculator.nextK();
137 | ECPoint p = basePointMultiplier.multiply(this.ecParams.getG(), k).normalize();
138 | r = e.add(p.getAffineXCoord().toBigInteger()).mod(n);
139 | } while(r.equals(ZERO));
140 |
141 | if (!r.add(k).equals(n)) {
142 | BigInteger dPlus1ModN = d.add(ONE).modInverse(n);
143 | BigInteger s = k.subtract(r.multiply(d)).mod(n);
144 | s = dPlus1ModN.multiply(s).mod(n);
145 | if (!s.equals(ZERO)) {
146 | try {
147 | return this.encoding.encode(this.ecParams.getN(), r, s);
148 | } catch (Exception var10) {
149 | throw new CryptoException("unable to encode signature: " + var10.getMessage(), var10);
150 | }
151 | }
152 | }
153 | }
154 | }
155 |
156 | private boolean verifySignature(BigInteger r, BigInteger s) {
157 | BigInteger n = this.ecParams.getN();
158 | if (r.compareTo(ONE) >= 0 && r.compareTo(n) < 0) {
159 | if (s.compareTo(ONE) >= 0 && s.compareTo(n) < 0) {
160 | byte[] eHash = this.digestDoFinal();
161 | BigInteger e = this.calculateE(n, eHash);
162 | BigInteger t = r.add(s).mod(n);
163 | if (t.equals(ZERO)) {
164 | return false;
165 | } else {
166 | ECPoint q = ((ECPublicKeyParameters)this.ecKey).getQ();
167 | ECPoint x1y1 = ECAlgorithms.sumOfTwoMultiplies(this.ecParams.getG(), s, q, t).normalize();
168 | if (x1y1.isInfinity()) {
169 | return false;
170 | } else {
171 | BigInteger expectedR = e.add(x1y1.getAffineXCoord().toBigInteger()).mod(n);
172 | return expectedR.equals(r);
173 | }
174 | }
175 | } else {
176 | return false;
177 | }
178 | } else {
179 | return false;
180 | }
181 | }
182 |
183 | private byte[] digestDoFinal() {
184 | byte[] result = new byte[this.digest.getDigestSize()];
185 | this.digest.doFinal(result, 0);
186 | this.reset();
187 | return result;
188 | }
189 |
190 | private byte[] getZ(byte[] userID) {
191 | this.digest.reset();
192 | this.addUserID(this.digest, userID);
193 | this.addFieldElement(this.digest, this.ecParams.getCurve().getA());
194 | this.addFieldElement(this.digest, this.ecParams.getCurve().getB());
195 | this.addFieldElement(this.digest, this.ecParams.getG().getAffineXCoord());
196 | this.addFieldElement(this.digest, this.ecParams.getG().getAffineYCoord());
197 | this.addFieldElement(this.digest, this.pubPoint.getAffineXCoord());
198 | this.addFieldElement(this.digest, this.pubPoint.getAffineYCoord());
199 | byte[] result = new byte[this.digest.getDigestSize()];
200 | this.digest.doFinal(result, 0);
201 | return result;
202 | }
203 |
204 | private void addUserID(Digest digest, byte[] userID) {
205 | int len = userID.length * 8;
206 | digest.update((byte)(len >> 8 & 255));
207 | digest.update((byte)(len & 255));
208 | digest.update(userID, 0, userID.length);
209 | }
210 |
211 | private void addFieldElement(Digest digest, ECFieldElement v) {
212 | byte[] p = v.getEncoded();
213 | digest.update(p, 0, p.length);
214 | }
215 |
216 | protected ECMultiplier createBasePointMultiplier() {
217 | return new FixedPointCombMultiplier();
218 | }
219 |
220 | protected BigInteger calculateE(BigInteger n, byte[] message) {
221 | return new BigInteger(1, message);
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SM2/SM2Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SM2;
2 |
3 | import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
4 | import org.bouncycastle.crypto.CryptoException;
5 | import org.bouncycastle.crypto.InvalidCipherTextException;
6 | import org.bouncycastle.crypto.engines.SM2Engine;
7 | import org.bouncycastle.crypto.engines.SM2Engine.Mode;
8 | import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
9 | import org.bouncycastle.crypto.params.ECPublicKeyParameters;
10 | import org.bouncycastle.crypto.params.ParametersWithRandom;
11 | import org.bouncycastle.crypto.signers.PlainDSAEncoding;
12 | import org.bouncycastle.math.ec.ECPoint;
13 | import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
14 |
15 | import java.math.BigInteger;
16 | import java.security.SecureRandom;
17 |
18 | /**
19 | * @author mtj
20 | * @date 2021/8/12
21 | * @desc 国产非对称加密算法
22 | * @email mtjsoft3@gmail.com
23 | *
24 | * 国产加密算法可有效规避老外的RSA算法等存在的脆弱性和“预置后门”的安全风险
25 | * 另一方面确保密码算法这一关键环节的自主可控
26 | *
27 | * 是我国基于更加安全先进的椭圆曲线密码机制(ECC),自主设计的非对称加密算法
28 | * ECC算法的单位安全强度远高于RSA算法,可以用较少的计算能力提供比RSA算法更高的安全强度,而所需的密钥长度却远比RSA算法低
29 | * 目前,基于ECC的SM2证书普遍采用256位密钥长度,加密强度等同于3072位RSA证书,远高于业界普遍采用的2048位RSA证书。
30 | */
31 | public class SM2Util {
32 | static final byte MODE_NO_COMPRESS = 4;
33 |
34 | private static final Mode SM2_CRYPT_MODE = Mode.C1C3C2;
35 |
36 | private SM2Util() {
37 | throw new UnsupportedOperationException("util class cant be instantiation");
38 | }
39 |
40 | public static boolean isValidPrivateKey(byte[] privateKey) {
41 | return SM2.Instance().isValidPrivateKey(privateKey);
42 | }
43 |
44 | public static byte[] getPublicKeyFromPrivateKey(byte[] privateKey) {
45 | return SM2.Instance().getPublicKeyFromPrivateKey(privateKey);
46 | }
47 |
48 | public static byte[][] generateKeyPair() {
49 | AsymmetricCipherKeyPair key = SM2.Instance().generateKeyPair();
50 | ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
51 | ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
52 | BigInteger privateKey = ecpriv.getD();
53 | ECPoint publicKey = ecpub.getQ();
54 | byte[] publicKeyEncoded = publicKey.getEncoded(false);
55 | if (publicKeyEncoded.length == 65) {
56 | publicKeyEncoded = ByteUtils.subArray(publicKeyEncoded, 1, publicKeyEncoded.length);
57 | }
58 | byte[] privateKeyEncoded = privateKey.toByteArray();
59 | if (privateKeyEncoded.length == 33) {
60 | privateKeyEncoded = ByteUtils.subArray(privateKeyEncoded, 1, privateKeyEncoded.length);
61 | }
62 | return new byte[][]{publicKeyEncoded, privateKeyEncoded};
63 | }
64 |
65 | public static byte[] encrypt(byte[] publicKey, byte[] data) {
66 | if (publicKey != null && publicKey.length != 0) {
67 | if (data != null && data.length != 0) {
68 | byte[] source = new byte[data.length];
69 | System.arraycopy(data, 0, source, 0, data.length);
70 | ECPublicKeyParameters publicKeyParameters = SM2.Instance().getPublicKeyParameters(publicKey);
71 | SM2Engine sm2Engine = new SM2Engine(SM2_CRYPT_MODE);
72 | sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
73 | byte[] bytes = new byte[0];
74 |
75 | try {
76 | bytes = sm2Engine.processBlock(source, 0, source.length);
77 | // 密文数据头部一位表示压缩模式,我们仅使用不压缩模式 0x04,因此移除该位
78 | return ByteUtils.subArray(bytes, 1);
79 | } catch (InvalidCipherTextException var7) {
80 | var7.printStackTrace();
81 | return new byte[0];
82 | }
83 | } else {
84 | return new byte[0];
85 | }
86 | } else {
87 | return new byte[0];
88 | }
89 | }
90 |
91 | public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) {
92 | if (privateKey != null && privateKey.length != 0) {
93 | if (encryptedData.length == 0) {
94 | return new byte[0];
95 | } else {
96 | encryptedData = ByteUtils.concatenate(new byte[]{4}, encryptedData);
97 | ECPrivateKeyParameters privateKeyParameters = SM2.Instance().getPrivateKeyParameters(privateKey);
98 | SM2Engine sm2Engine = new SM2Engine(SM2_CRYPT_MODE);
99 | sm2Engine.init(false, privateKeyParameters);
100 | try {
101 | return sm2Engine.processBlock(encryptedData, 0, encryptedData.length);
102 | } catch (InvalidCipherTextException var5) {
103 | var5.printStackTrace();
104 | return new byte[0];
105 | }
106 | }
107 | } else {
108 | return new byte[0];
109 | }
110 | }
111 |
112 | public static byte[] sign(byte[] privateKey, byte[] sourceData) {
113 | ECPrivateKeyParameters privateKeyParameters = SM2.Instance().getPrivateKeyParameters(privateKey);
114 | SM2Signer signer = new SM2Signer(new PlainDSAEncoding());
115 | signer.init(true, privateKeyParameters);
116 | signer.update(sourceData, 0, sourceData.length);
117 | try {
118 | return signer.generateSignature();
119 | } catch (CryptoException var5) {
120 | return new byte[0];
121 | }
122 | }
123 |
124 | public static boolean verifySign(byte[] publicKey, byte[] sourceData, byte[] signData) {
125 | ECPublicKeyParameters publicKeyParameters = SM2.Instance().getPublicKeyParameters(publicKey);
126 | SM2Signer signer = new SM2Signer(new PlainDSAEncoding());
127 | signer.init(false, publicKeyParameters);
128 | signer.update(sourceData, 0, sourceData.length);
129 | return signer.verifySignature(signData);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SM3/SM3Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SM3;
2 |
3 | import org.bouncycastle.crypto.digests.SM3Digest;
4 |
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.nio.MappedByteBuffer;
9 | import java.nio.channels.FileChannel;
10 |
11 | import cn.mtjsoft.lib_encryption.utils.Util;
12 |
13 | /**
14 | * @author mtj
15 | * @date 2021/8/12
16 | * @desc 国产摘要算法
17 | * @email mtjsoft3@gmail.com
18 | *
19 | * 国产加密算法可有效规避老外的RSA算法等存在的脆弱性和“预置后门”的安全风险
20 | * 另一方面确保密码算法这一关键环节的自主可控
21 | *
22 | * SM3摘要算法是我国自主设计的密码摘要算法,安全性要高于MD5算法(128位)和SHA-1算法(160位),SM3算法的压缩函数与SHA-256具有相似结构,但设计更加复杂
23 | */
24 | public class SM3Util {
25 | /**
26 | * SM3 加密
27 | *
28 | * @param source 原始数组
29 | * @return 加密后的,32位数组
30 | */
31 | public static byte[] encryptInner(byte[] source) {
32 | byte[] result = new byte[32];
33 | SM3Digest sm3 = new SM3Digest();
34 | sm3.update(source, 0, source.length);
35 | sm3.doFinal(result, 0);
36 | return result;
37 | }
38 |
39 | public static String encryptInner(String input) {
40 | SM3Digest digest = new SM3Digest();
41 | byte[] sourceBytes = input.getBytes();
42 | digest.update(sourceBytes, 0, sourceBytes.length);
43 | byte[] result = new byte[32];
44 | digest.doFinal(result, 0);
45 | return Util.byte2HexStr(result);
46 | }
47 |
48 | /**
49 | * 计算文件摘要
50 | */
51 | public static String getMd5ByFile(File file) {
52 | String result = "";
53 | if (!file.isFile()) {
54 | return result;
55 | }
56 | SM3Digest digest = null;
57 | FileInputStream in = null;
58 | byte[] buffer = new byte[1024];
59 | int len;
60 | try {
61 | digest = new SM3Digest();
62 | in = new FileInputStream(file);
63 | while ((len = in.read(buffer, 0, 1024)) != -1) {
64 | digest.update(buffer, 0, len);
65 | }
66 | in.close();
67 | byte[] bytes = new byte[32];
68 | digest.doFinal(bytes, 0);
69 | result = Util.byte2HexStr(bytes);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | result = "";
73 | }
74 | return result;
75 | }
76 |
77 | /**
78 | * 计算文件摘要
79 | *
80 | * 采用nio的方式
81 | */
82 | public static String getMd5ByFileNio(File file) {
83 | String result = "";
84 | if (!file.isFile()) {
85 | return result;
86 | }
87 | FileInputStream in = null;
88 | try {
89 | in = new FileInputStream(file);
90 | MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
91 | result = Util.byte2HexStr(encryptInner(byteBuffer.array()));
92 | } catch (Exception e) {
93 | e.printStackTrace();
94 | } finally {
95 | if (null != in) {
96 | try {
97 | in.close();
98 | } catch (IOException e) {
99 | e.printStackTrace();
100 | }
101 | }
102 | }
103 | return result;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/SM4/SM4Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.SM4;
2 |
3 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.spec.IvParameterSpec;
7 | import javax.crypto.spec.SecretKeySpec;
8 |
9 | import cn.mtjsoft.lib_encryption.utils.Util;
10 |
11 | /**
12 | * @author mtj
13 | * @date 2021/8/12
14 | * @desc 国产对称加密算法
15 | * @email mtjsoft3@gmail.com
16 | *
17 | * 国产加密算法可有效规避老外的RSA算法等存在的脆弱性和“预置后门”的安全风险
18 | * 另一方面确保密码算法这一关键环节的自主可控
19 | *
20 | * SM4分组密码算法是我国自主设计的分组对称密码算法
21 | */
22 | public class SM4Util {
23 | public static final String SM4_CBC_NOPADDING = "SM4/CBC/NoPadding";
24 |
25 | public static final String SM4_CBC_PKCS5 = "SM4/CBC/PKCS5Padding";
26 |
27 | public static final String SM4_ECB_NOPADDING = "SM4/ECB/NoPadding";
28 |
29 | public static final String SM4_ECB_PKCS5 = "SM4/ECB/PKCS5Padding";
30 |
31 | private static final BouncyCastleProvider BC_PROVIDER = new BouncyCastleProvider();
32 |
33 | private SM4Util() {
34 | throw new UnsupportedOperationException("util class cant be instantiation");
35 | }
36 |
37 | /**
38 | * 获取随机密钥
39 | */
40 | public static byte[] createSM4Key() {
41 | return Util.genRandomBytes(16);
42 | }
43 |
44 | public static byte[] encrypt(byte[] source, byte[] key) {
45 | return encrypt(source, key, SM4_CBC_PKCS5, new byte[16]);
46 | }
47 |
48 | public static byte[] decrypt(byte[] source, byte[] key) {
49 | return decrypt(source, key, SM4_CBC_PKCS5, new byte[16]);
50 | }
51 |
52 | public static byte[] encrypt(byte[] source, byte[] key, String mode, byte[] iv) {
53 | return doSM4(true, source, key, mode, iv);
54 | }
55 |
56 | public static byte[] decrypt(byte[] source, byte[] key, String mode, byte[] iv) {
57 | return doSM4(false, source, key, mode, iv);
58 | }
59 |
60 | private static byte[] doSM4(boolean forEncryption, byte[] source, byte[] key, String mode, byte[] iv) {
61 | try {
62 | int cryptMode = forEncryption ? 1 : 2;
63 | SecretKeySpec sm4Key = new SecretKeySpec(key, "SM4");
64 | Cipher cipher = Cipher.getInstance(mode, BC_PROVIDER);
65 | if (iv == null) {
66 | cipher.init(cryptMode, sm4Key);
67 | } else {
68 | IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
69 | cipher.init(cryptMode, sm4Key, ivParameterSpec);
70 | }
71 | return cipher.doFinal(source);
72 | } catch (Exception var9) {
73 | var9.printStackTrace();
74 | return new byte[0];
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib_encryption/src/main/java/cn/mtjsoft/lib_encryption/utils/Util.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.security.SecureRandom;
6 | import java.util.Arrays;
7 | import java.util.Locale;
8 |
9 | import static java.lang.System.arraycopy;
10 |
11 | /**
12 | * @author mtj
13 | * @date 2021/8/6
14 | * @desc
15 | * @email mtjsoft3@gmail.com
16 | */
17 | public class Util {
18 | /**
19 | * 十六进制字符串转换为byte[]
20 | *
21 | * @param hexStr 需要转换为byte[]的字符串
22 | * @return 转换后的byte[]
23 | */
24 | public static byte[] hexStr2Bytes(String hexStr) {
25 | if (TextUtils.isEmpty(hexStr)) {
26 | return null;
27 | }
28 | /*对输入值进行规范化整理*/
29 | hexStr = hexStr.trim().replace(" ", "").toUpperCase(Locale.US);
30 | //处理值初始化
31 | int m = 0, n = 0;
32 | int iLen = hexStr.length() / 2; //计算长度
33 | byte[] ret = new byte[iLen]; //分配存储空间
34 |
35 | for (int i = 0; i < iLen; i++) {
36 | m = i * 2 + 1;
37 | n = m + 1;
38 | ret[i] = (byte) (Integer.decode("0x" + hexStr.substring(i * 2, m) + hexStr.substring(m, n)) & 0xFF);
39 | }
40 | return ret;
41 | }
42 |
43 |
44 | /**
45 | * byte[]转换为十六进制字符串
46 | *
47 | * @param bytes 需要转换为字符串的byte[]
48 | * @return 转换后的十六进制字符串
49 | */
50 | public static String byte2HexStr(byte[] bytes) {
51 | if (bytes == null) {
52 | return "";
53 | }
54 | StringBuilder hs = new StringBuilder();
55 | String stmp = "";
56 | for (byte aByte : bytes) {
57 | stmp = (Integer.toHexString(aByte & 0XFF));
58 | if (stmp.length() == 1) {
59 | hs.append("0");
60 | hs.append(stmp);
61 | } else {
62 | hs.append(stmp);
63 | }
64 | }
65 | return hs.toString().toUpperCase();
66 | }
67 |
68 | /**
69 | * 随机生成一个指定长度的字节数组
70 | *
71 | * @param len 给定的长度
72 | */
73 | public static byte[] genRandomBytes(int len) {
74 | byte[] seed = new byte[len];
75 | SecureRandom random = new SecureRandom();
76 | random.nextBytes(seed);
77 | return seed;
78 | }
79 |
80 |
81 | /**
82 | * pkcs7填充
83 | * source : 源数据
84 | * blocksize : 要填充的倍数
85 | */
86 | public static byte[] pkcs7_pad(byte[] source, int blocksize) {
87 | int sourceLength = source.length;
88 | int padDataLen = blocksize - (sourceLength % blocksize);
89 | int afterPadLen = sourceLength + padDataLen;
90 | byte[] paddingResult = new byte[afterPadLen];
91 | System.arraycopy(source, 0, paddingResult, 0, sourceLength);
92 | for (int i = sourceLength; i < afterPadLen; i++) {
93 | paddingResult[i] = (byte) padDataLen;
94 | }
95 | return paddingResult;
96 | }
97 |
98 | /**
99 | * pkcs7 截取
100 | *
101 | * @throws Exception
102 | */
103 | public static byte[] pkcs7_unpad(byte[] data) throws Exception {
104 | int lastValue = data[data.length - 1];
105 | byte[] unpad = new byte[data.length - lastValue];
106 | System.arraycopy(data, 0, unpad, 0, unpad.length);
107 | return unpad;
108 | }
109 |
110 | /*
111 | * 将两个byte数组拼接成一个byte数组
112 | */
113 | public static byte[] pinJie2(byte[] a, byte[] b) {
114 | byte[] bytes = Arrays.copyOf(a, a.length + b.length);
115 | System.arraycopy(b, 0, bytes, a.length, b.length);
116 | return bytes;
117 | }
118 |
119 | /*
120 | * 将三个byte数组拼接成一个byte数组
121 | */
122 | public static byte[] pinJie3(byte[] a, byte[] b, byte[] c) {
123 | byte[] data = new byte[a.length + b.length + c.length];
124 | arraycopy(a, 0, data, 0, a.length);
125 | arraycopy(b, 0, data, a.length, b.length);
126 | arraycopy(c, 0, data, a.length + b.length, c.length);
127 | return data;
128 | }
129 |
130 | /**
131 | * 变长拼接
132 | *
133 | * @param bytes 数据源
134 | * @return 结果
135 | */
136 | public static byte[] pinJie(byte[]... bytes) {
137 | int length = 0;
138 | for (byte[] temp : bytes) {
139 | length += temp.length;
140 | }
141 | byte[] totalData = new byte[length];
142 | int tempLength = 0;
143 | for (byte[] temp : bytes) {
144 | // Object src, int srcPos, Object dest , int destPos, int length
145 | arraycopy(temp, 0, totalData, tempLength, temp.length);
146 | tempLength += temp.length;
147 | }
148 | return totalData;
149 | }
150 |
151 | /**
152 | * 把一个整形int转换成byte数组 低位再前高位在后
153 | */
154 | public static byte[] intToByte4(int i) {
155 | byte[] targets = new byte[4];
156 | targets[3] = (byte) (i & 0xFF);
157 | targets[2] = (byte) (i >> 8 & 0xFF);
158 | targets[1] = (byte) (i >> 16 & 0xFF);
159 | targets[0] = (byte) (i >> 24 & 0xFF);
160 | return targets;
161 | }
162 |
163 | /**
164 | * 把一个byte数组转换成 整形int
165 | */
166 | public static int byte4ToInt(byte[] bytes) {
167 | int b0 = bytes[0] & 0xFF;
168 | int b1 = bytes[1] & 0xFF;
169 | int b2 = bytes[2] & 0xFF;
170 | int b3 = bytes[3] & 0xFF;
171 | return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
172 | }
173 |
174 | /*
175 | * 截取byte数组 count - 截取的长度
176 | */
177 | public static byte[] subBytes(byte[] src, int begin, int count) {
178 | byte[] bs = new byte[count];
179 | System.arraycopy(src, begin, bs, 0, count);
180 | return bs;
181 | }
182 |
183 | /*
184 | * 截取byte数组 count - 末尾下标
185 | */
186 | public static byte[] subBytes1(byte[] src, int begin, int count) {
187 | byte[] bs = new byte[count - begin];
188 | System.arraycopy(src, begin, bs, 0, count - begin);
189 | return bs;
190 | }
191 |
192 | /**
193 | * 填充128字节
194 | */
195 | public static byte[] zerofill128(byte[] bt) {
196 | byte[] bytes = new byte[128];
197 | Arrays.fill(bytes, 0, 112, (byte) 0x00);
198 | System.arraycopy(bt, 0, bytes, 112, 16);
199 | return bytes;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/lib_encryption/src/test/java/android/text/TextUtils.java:
--------------------------------------------------------------------------------
1 | package android.text;
2 |
3 | /**
4 | * @author mtj
5 | * @date 2021/8/31
6 | * @desc
7 | * @email mtjsoft3@gmail.com
8 | */
9 | public class TextUtils {
10 | public static boolean isEmpty(CharSequence str) {
11 | if (str == null || str.equals("")) {
12 | return true;
13 | }
14 | return false;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib_encryption/src/test/java/cn/mtjsoft/lib_encryption/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.mtjsoft.lib_encryption;
2 |
3 | import org.junit.Test;
4 |
5 | import java.security.KeyPair;
6 | import java.security.PrivateKey;
7 | import java.security.PublicKey;
8 | import java.util.Arrays;
9 |
10 | import cn.mtjsoft.lib_encryption.AES.AESUtil;
11 | import cn.mtjsoft.lib_encryption.BASE64.Base64Util;
12 | import cn.mtjsoft.lib_encryption.MD5.MD5Util;
13 | import cn.mtjsoft.lib_encryption.RSA.RSAUtil;
14 | import cn.mtjsoft.lib_encryption.SHA.SHAUtil;
15 | import cn.mtjsoft.lib_encryption.SM2.SM2Util;
16 | import cn.mtjsoft.lib_encryption.SM3.SM3Util;
17 | import cn.mtjsoft.lib_encryption.SM4.SM4Util;
18 | import cn.mtjsoft.lib_encryption.utils.Util;
19 |
20 | /**
21 | * Example local unit test, which will execute on the development machine (host).
22 | *
23 | * @see Testing documentation
24 | */
25 | public class ExampleUnitTest {
26 | /**
27 | * AES对称加密
28 | */
29 | @Test
30 | public void aesTest() {
31 | byte[] key = AESUtil.generateKey();
32 | System.out.println("key: " + Util.byte2HexStr(key));
33 | String dataString = "我是测试aesTest明文";
34 | System.out.println("明文:$dataString");
35 | byte[] encrypt = AESUtil.encrypt(dataString.getBytes(), key);
36 | String encryptHexStr = Util.byte2HexStr(encrypt);
37 | System.out.println("AES加密: " + encryptHexStr);
38 | String decryptHexStr = new String(AESUtil.decrypt(encrypt, key));
39 | System.out.println("AES解密: " + decryptHexStr);
40 | }
41 |
42 | /**
43 | * BASE64编码
44 | */
45 | @Test
46 | public void base64Test() {
47 | String dataString = "我是测试base64Test明文";
48 | System.out.println("明文:$dataString");
49 | String encode = Base64Util.encode(dataString.getBytes());
50 | System.out.println("base64编码: " + encode);
51 | System.out.println("base64解码: " + new String(Base64Util.decode(encode)));
52 | }
53 |
54 | /**
55 | * MD5摘要
56 | */
57 | @Test
58 | public void md5Test() {
59 | String dataString = "我是测试md5Test明文";
60 | System.out.println("明文:" + dataString);
61 | System.out.println("md5摘要: " + MD5Util.stringMD5(dataString));
62 | }
63 |
64 | /**
65 | * SHA
66 | */
67 | @Test
68 | public void shaTest() {
69 | String dataString = "我是测试shaTest明文";
70 | System.out.println("明文:" + dataString);
71 | System.out.println("sha1摘要: " + SHAUtil.stringSHA(dataString, SHAUtil.SHA1));
72 | System.out.println("sha256摘要: " + SHAUtil.stringSHA(dataString, SHAUtil.SHA256));
73 | }
74 |
75 | /**
76 | * RSA非对称加密
77 | */
78 | @Test
79 | public void rsaTest() throws Exception {
80 | String dataString = "我是测试rsaTest明文";
81 | System.out.println("明文:" + dataString);
82 | KeyPair key = RSAUtil.generateRSAKeyPair();
83 | // 获取公私钥
84 | PrivateKey privateKey = key.getPrivate();
85 | PublicKey publicKey = key.getPublic();
86 | byte[] encryptByPublicKey = RSAUtil.encryptByPublicKey(dataString.getBytes(), publicKey);
87 | System.out.println("公钥加密明文:" + Util.byte2HexStr(encryptByPublicKey));
88 | System.out.println("私钥解密:" + new String(RSAUtil.decryptByPrivateKey(encryptByPublicKey, privateKey)));
89 |
90 | byte[] encryptByPrivateKey = RSAUtil.encryptByPrivateKey(dataString.getBytes(), privateKey);
91 | System.out.println("私钥加密明文:" + Util.byte2HexStr(encryptByPrivateKey));
92 | System.out.println("公钥解密:" + new String(RSAUtil.decryptByPublicKeyKey(encryptByPrivateKey, publicKey)));
93 |
94 | byte[] signWithSHA256 = RSAUtil.signWithSHA256(dataString.getBytes(), privateKey);
95 | System.out.println("私钥对明文数据SHA256签名:" + Util.byte2HexStr(signWithSHA256));
96 | byte[] signWithMD5 = RSAUtil.signWithMD5(dataString.getBytes(), privateKey);
97 | System.out.println("私钥对明文数据MD5签名:" + Util.byte2HexStr(signWithMD5));
98 |
99 | boolean verifySignWithSHA256 = RSAUtil.verifySignWithSHA256(dataString.getBytes(), signWithSHA256, publicKey);
100 | System.out.println("公钥对SHA256签名验签:" + verifySignWithSHA256);
101 | boolean verifySignWithMD5 = RSAUtil.verifySignWithMD5(dataString.getBytes(), signWithMD5, publicKey);
102 | System.out.println("公钥对MD5签名验签:" + verifySignWithMD5);
103 | }
104 |
105 | /**
106 | * 国产SM2非对称加密
107 | */
108 | @Test
109 | public void sm2Test() {
110 | String dataString = "我是测试sm2Test明文";
111 | System.out.println("明文:" + dataString);
112 |
113 | // 获取随机的公私钥
114 | byte[][] key = SM2Util.generateKeyPair();
115 | byte[] publicKey = key[0];
116 | byte[] privateKey = key[1];
117 |
118 | System.out.println("私钥:" + privateKey.length + " " + Util.byte2HexStr(privateKey));
119 | System.out.println("公钥:" + Util.byte2HexStr(publicKey));
120 |
121 | byte[] encryptByPublicKey = SM2Util.encrypt(publicKey, dataString.getBytes());
122 | System.out.println("公钥加密明文:" + Util.byte2HexStr(encryptByPublicKey));
123 | System.out.println("私钥解密:" + new String(SM2Util.decrypt(privateKey, encryptByPublicKey)));
124 |
125 | byte[] sign = SM2Util.sign(privateKey, encryptByPublicKey);
126 | System.out.println("签名:" + Util.byte2HexStr(sign));
127 | boolean verifySign = SM2Util.verifySign(publicKey, encryptByPublicKey, sign);
128 | System.out.println("验签:" + verifySign);
129 | }
130 |
131 | /**
132 | * 国产SM3摘要
133 | */
134 | @Test
135 | public void sm3Test() {
136 | String dataString = "我是测试sm3Test明文";
137 | System.out.println("明文:" + dataString);
138 | System.out.println("sm3摘要: " + SM3Util.encryptInner(dataString));
139 | }
140 |
141 | /**
142 | * 国产SM4对称加密
143 | */
144 | @Test
145 | public void sm4Test() {
146 | String dataString = "我是测试sm4Test明文";
147 | System.out.println("明文:" + dataString);
148 |
149 | byte[] key = SM4Util.createSM4Key();
150 | System.out.println("密钥:" + Util.byte2HexStr(key));
151 |
152 | byte[] encryptCBC = SM4Util.encrypt(dataString.getBytes(), key, SM4Util.SM4_CBC_PKCS5, new byte[16]);
153 | System.out.println("CBC加密:" + Util.byte2HexStr(encryptCBC));
154 | System.out.println("CBC解密:" + new String(SM4Util.decrypt(encryptCBC, key, SM4Util.SM4_CBC_PKCS5, new byte[16])));
155 |
156 | byte[] encryptECB = SM4Util.encrypt(dataString.getBytes(), key, SM4Util.SM4_ECB_PKCS5, null);
157 | System.out.println("ECB加密:" + Util.byte2HexStr(encryptECB));
158 | System.out.println("ECB解密:" + new String(SM4Util.decrypt(encryptECB, key, SM4Util.SM4_ECB_PKCS5, null)));
159 | }
160 | }
--------------------------------------------------------------------------------
/publish-mavencentral.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'signing'
3 |
4 | //第 1 处
5 | ext["PUBLISH_VERSION"] = '' //发布的版本
6 | ext["PUBLISH_GROUP_ID"] = '' //分组ID
7 | ext["PUBLISH_ARTIFACT_ID"] = '' //
8 | ext["signing.keyId"] = '' //签名的密钥后8位
9 | ext["signing.password"] = '' //签名设置的密码
10 | ext["signing.secretKeyRingFile"] = '' //生成的secring.gpg文件目录
11 | ext["ossrhUsername"] = '' //sonatype用户名
12 | ext["ossrhPassword"] = '' //sonatype密码
13 | // 遍历赋值
14 | File secretPropsFile = project.rootProject.file('local.properties')
15 | if (secretPropsFile.exists()) {
16 | println "Found secret props file, loading props"
17 | Properties p = new Properties()
18 | p.load(new FileInputStream(secretPropsFile))
19 | p.each { name, value ->
20 | ext[name] = value
21 | }
22 | } else {
23 | println "No props file, loading env vars"
24 | }
25 |
26 | afterEvaluate {
27 | publishing {
28 | repositories {
29 | // The repository to publish to, Sonatype/MavenCentral
30 | maven {
31 | //第 6 处 推送至远端的中央仓库,一旦发布中央仓库版本,旧版本无法回撤
32 | //仓库默认不支持Https,所有这里设置成false.
33 | // allowInsecureProtocol = false
34 | name = PUBLISH_ARTIFACT_ID
35 | // 中央 release 仓库: "https://s01.oss.sonatype.org/content/repositories/releases"
36 | // 中央 snapshot 仓库:"https://s01.oss.sonatype.org/content/repositories/snapshots"
37 | // 暂存库 "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2"
38 | def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
39 | def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
40 | url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
41 |
42 | // The username and password we've fetched earlier
43 | credentials {
44 | username ossrhUsername
45 | password ossrhPassword
46 | }
47 | }
48 | maven {
49 | //第 6 处 推送至本地仓库
50 | //仓库默认不支持Https,所有这里设置成false.
51 | // allowInsecureProtocol = false
52 | name = 'Local'
53 | url = uri('../ZLocalRepo')
54 | }
55 | }
56 | publications {
57 | release(MavenPublication) {
58 | println("publish-maven Log-------> PUBLISH_GROUP_ID: $PUBLISH_GROUP_ID; PUBLISH_ARTIFACT_ID: $PUBLISH_ARTIFACT_ID; PUBLISH_VERSION: $PUBLISH_VERSION")
59 | // The coordinates of the library, being set from variables that
60 |
61 | //第 2 处
62 | groupId PUBLISH_GROUP_ID
63 | artifactId PUBLISH_ARTIFACT_ID
64 | version PUBLISH_VERSION
65 |
66 | //添加这个,否则aar文件不上传
67 | // from components.release
68 | artifact("$buildDir/outputs/aar/cshtreadcard-release.aar")
69 | // artifact androidSourcesJar
70 |
71 | // Self-explanatory metadata for the most part
72 | pom {
73 | //第 3 处
74 | name = PUBLISH_ARTIFACT_ID
75 | description = '' //项目描述
76 | url = 'https://github.com/mtjsoft/ReadCardSdk' //项目github链接
77 | licenses {
78 | license {
79 | //协议类型,一般默认Apache License2.0的话不用改:
80 | name = 'The Apache License, Version 2.0'
81 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
82 | }
83 | }
84 | developers {
85 | developer {
86 | //第 4 处
87 | id = 'mtjsoft' //你的sonatype用户名
88 | name = 'mtjsoft' //你的sonatype用户名
89 | email = 'mtjsoft3@gmail.com' //你的sonatype注册邮箱
90 | }
91 | }
92 | // Version control info, if you're using GitHub, follow the format as seen here
93 | scm {
94 | //第 5 处
95 | //修改成你的Git地址:
96 | connection = 'scm:git@github.com:mtjsoft/ReadCardSdk.git'
97 | developerConnection = 'scm:git@github.com:mtjsoft/ReadCardSdk.git'
98 | //分支地址:
99 | url = 'https://github.com/mtjsoft/ReadCardSdk'
100 | }
101 | // A slightly hacky fix so that your POM will include any transitive dependencies
102 | // that your library builds upon
103 | withXml {
104 | def dependenciesNode = asNode().appendNode('dependencies')
105 |
106 | project.configurations.implementation.allDependencies.each {
107 | def dependencyNode = dependenciesNode.appendNode('dependency')
108 | dependencyNode.appendNode('groupId', it.group)
109 | dependencyNode.appendNode('artifactId', it.name)
110 | dependencyNode.appendNode('version', it.version)
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 | signing {
118 | sign publishing.publications
119 | // sign publishing.publications.release
120 | // sign configurations.archives
121 | }
122 | }
123 |
124 |
125 | // 生成文档注释
126 | //task androidJavadocs(type: Javadoc) {
127 | // // 设置源码所在的位置
128 | // source = android.sourceSets.main.java.srcDirs
129 | //}
130 | //
131 | //// 将文档打包成jar,生成javadoc.jar
132 | //task androidJavadocsJar(type: Jar) {
133 | // // 指定文档名称
134 | // archiveClassifier.set('javadoc')
135 | // from androidJavadocs.destinationDir
136 | //}
137 | //
138 | //// 将源码打包 ,生成sources.jar
139 | //task androidSourcesJar(type: Jar) {
140 | // archiveClassifier.set('sources')
141 | // from android.sourceSets.main.java.srcDirs
142 | //
143 | // exclude "**/R.class"
144 | // exclude "**/BuildConfig.class"
145 | //}
146 | //
147 | ////配置需要上传到maven仓库的文件
148 | //artifacts {
149 | // archives androidSourcesJar //将源码打包进aar,这样使用方可以看到方法注释.
150 | // archives androidJavadocsJar //将注释打包进aar
151 | //}
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':lib_encryption'
2 | rootProject.name = "MyEncryptionDemo"
3 | include ':app'
4 |
--------------------------------------------------------------------------------