├── .gitignore
├── src
└── main
│ ├── webapp
│ └── WEB-INF
│ │ └── web.xml
│ └── java
│ └── com
│ └── muarine
│ └── security
│ ├── rsa_public_key.pem.crt
│ ├── Coder.java
│ ├── private_key.pem
│ ├── MD5Utils.java
│ ├── Base64Utils.java
│ ├── AESUtil.java
│ └── RSAUtils.java
├── README.md
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 | /target/
14 | /.settings/
15 | .project
16 | .classpath
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rsa_aes_md5 加密算法
2 |
3 | ## RSA(SHA1withRSA/pem私钥0/crt证书公钥) + AES(256/AES/CBC/PKCS5Padding)
4 |
5 | ## 公私钥生成:
6 | ```bash
7 | openssl genrsa -out rsa_private_key.pem 2048
8 | openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem
9 | openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
10 | openssl req -new -x509 -days 2048 -key rsa_private_key.pem -out rsa_public_key.crt
11 | ```
12 |
13 | ```text
14 | 非对称加密算法:RSA
15 | 加密模式:SHA1withRSA
16 | PS:解析私钥.pem文件时需对字符串进行Base64解码
17 |
18 | 对称加密算法:AES
19 | 密钥Key随机生成位数:256
20 | 加密模式:AES/CBC/PKCS5Padding
21 | ```
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/rsa_public_key.pem.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDhTCCAm2gAwIBAgIJAPtt2p5wr2zDMA0GCSqGSIb3DQEBBQUAMFkxCzAJBgNV
3 | BAYTAlpOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5nMQ4wDAYD
4 | VQQKDAVSVE1BUDEWMBQGA1UEAwwNd3d3LnJ0bWFwLmNvbTAeFw0xNTA2MjMwMzI0
5 | NDRaFw0yMTAxMzAwMzI0NDRaMFkxCzAJBgNVBAYTAlpOMRAwDgYDVQQIDAdCZWlq
6 | aW5nMRAwDgYDVQQHDAdCZWlqaW5nMQ4wDAYDVQQKDAVSVE1BUDEWMBQGA1UEAwwN
7 | d3d3LnJ0bWFwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKoP
8 | y7a0RnJfVwnoeLe5r6Ec7jvwkbBids4f1dtt8eamFguGJ9ocdNwRgZ3Op6cyIKeh
9 | +FLDUx/TCZnxvmrNd+O4u4nXTD4OQTYZYfoNDiBhIVCqyY/IXQx3x8xZkhGtRBwa
10 | pr5Asb+6XO0FqXousZLoX6NCuSAXZTy4F/N0+o9oozwfI9WLqyAnlhwqwe/hN1/D
11 | LwruZ3gMFWCgeaA88y/Js2hn+UB3wRiRH9Hkv2jVz6o78772tUhovx6x9N37s5TF
12 | VIDa7DlQkVtDWbD+jW1t7IAaLmbTSxj7PpcORgltnnTc0pfAgU3pxQPqJg6HsHWy
13 | uKsIVZJVtjV+7bp0sesCAwEAAaNQME4wHQYDVR0OBBYEFALT/moY3f2bHPxP8P3q
14 | ljsUVAInMB8GA1UdIwQYMBaAFALT/moY3f2bHPxP8P3qljsUVAInMAwGA1UdEwQF
15 | MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG8a0HmT2DK5VeOTFpfTovq/io5+Khz/
16 | oBajOLI7+SH/Umc/cJq4AnSPmJAEpmCWlljHz5PpWVOnhuETJ1BqtoxpZfHz3Csq
17 | H6KSuMbu5miZquQEB/Fr5DOP0sOnOxfFA06Ut7d0zRRqox1+UkCm0Q1J4mO7Z9fO
18 | jcP7vfTk0XO0JGsBOIuEIqMfDkQEvSUXLdW18tqOFceDQYHUcICS8gvfankZFGNG
19 | zi4Kj5oIPrRN6VnpvTKMA9RT1g6i7Mp3UC7RFgyRj5RLdrKM4KZF2tNL7Jxrt8+v
20 | wlijg2A27teJuUTokB/mkZheIFMIl7A5sjTi5qHiEFiHddlIEmR3B7A=
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/Coder.java:
--------------------------------------------------------------------------------
1 | package com.muarine.security;
2 |
3 | import java.security.MessageDigest;
4 |
5 | import org.apache.commons.codec.binary.Base64;
6 |
7 |
8 |
9 | public class Coder {
10 |
11 | public static final String KEY_SHA="SHA";
12 | public static final String KEY_MD5="MD5";
13 |
14 | /**
15 | * BASE64解密
16 | * @param key
17 | * @return
18 | * @throws Exception
19 | */
20 | public static byte[] decryptBASE64(String key) throws Exception{
21 | return Base64.decodeBase64(key);
22 | }
23 |
24 | /**
25 | * BASE64加密
26 | * @param key
27 | * @return
28 | * @throws Exception
29 | */
30 | public static String encryptBASE64(byte[] key)throws Exception{
31 | return Base64.encodeBase64String(key);
32 | }
33 |
34 | /**
35 | * MD5加密
36 | * @param data
37 | * @return
38 | * @throws Exception
39 | */
40 | public static byte[] encryptMD5(byte[] data)throws Exception{
41 | MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
42 | md5.update(data);
43 | return md5.digest();
44 | }
45 |
46 | /**
47 | * SHA加密
48 | * @param data
49 | * @return
50 | * @throws Exception
51 | */
52 | public static byte[] encryptSHA(byte[] data)throws Exception{
53 | MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
54 | sha.update(data);
55 | return sha.digest();
56 | }
57 | }
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/private_key.pem:
--------------------------------------------------------------------------------
1 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCqD8u2tEZyX1cJ
2 | 6Hi3ua+hHO478JGwYnbOH9XbbfHmphYLhifaHHTcEYGdzqenMiCnofhSw1Mf0wmZ
3 | 8b5qzXfjuLuJ10w+DkE2GWH6DQ4gYSFQqsmPyF0Md8fMWZIRrUQcGqa+QLG/ulzt
4 | Bal6LrGS6F+jQrkgF2U8uBfzdPqPaKM8HyPVi6sgJ5YcKsHv4Tdfwy8K7md4DBVg
5 | oHmgPPMvybNoZ/lAd8EYkR/R5L9o1c+qO/O+9rVIaL8esfTd+7OUxVSA2uw5UJFb
6 | Q1mw/o1tbeyAGi5m00sY+z6XDkYJbZ503NKXwIFN6cUD6iYOh7B1srirCFWSVbY1
7 | fu26dLHrAgMBAAECggEAaJz86PBu4Y6KoVqzX/nG82ozlwW+6W04vkXRLYGtrAAB
8 | Uad+PmsA7BuMy4HDmlN4yQYXFvp22P3eSyftxg+NL7WFEB80FHx6Wwg0QDjltr9p
9 | WhElmuBbdP7+FlQHSf53Bn7SkfiEH3hKD7hK8BFnRQLTSkASV45sxXRNr4MHW023
10 | HHzYXC+1zl0NNC2bkf2KICg+lq2ACPTHVP1KPIupWj0TNY5w3igakZ04L2hKu6hq
11 | Gr5Nms8vuc0gJxn0iWTcTTopLB8rlVOikZlN7PxNpHyBLXJuk9AnGkOuinlkVENB
12 | ggURgOFLK1NKZkB2ab0mS8GNj3jsfCgLMr7y+MEowQKBgQDaRZr9OZ6Ayp1EdzzE
13 | 3rAyumkQyMZxYmcGW3iYYOIHnIgER37JcdWULzGDAQkdLtXS8oICZA09+lfEQ2+o
14 | nYVqrnhvZLHN0aeYE3pHpC/q9ink9vqnB/LYdXrlTThpE6xsV+kvJg95gvIbZVVY
15 | cQvYc1Jba9Tf/CuH35WkMwn3CwKBgQDHdOtiNb3r5OlPrJ7lBbQh0DfucybvNGFC
16 | CZcpfg4+o98uHjognts4G8MUg/6da4DpoOvBm9rM7afCw/qttzRUTbuEAq0JENdv
17 | 9DbGqTtA7mqE1YJ8qBgJQ6SqZvnX65dJiVYKffyE056bDJOkrOxibvMXb1S1Sgml
18 | 0YNSIPV8oQKBgQDOSsL1WaPIrbZ9owQ4PQ/iofPy/Q8w0oP0qjcMLWTzNKoJAVl/
19 | IqttZj0xR6VJg55rxO/DOrSZQyX4RJQflOEntsX04gJ6OBBh1ubXFwKC2y01TYgQ
20 | nZ6TnlUMqzMJfKKVs3CcMyik+3G/GsLS1+UOKdBIv11uZHLv9A0GJ4bfiQKBgHoG
21 | pwdjt7j9SFwtUNzu22CggceJfbV0x1fehDOnYlGiciVF6uwQJDA0k+oWQwzOO4Uz
22 | pWjC0F71uuAmhFQJNKOrFuDRvklAm31r3KM33/9+nX59HaLkOCha0QBLlekqwlkE
23 | A7bRk080JOHZFO73uHsUQ/b/bsSm8jYXcw8pCOdhAoGBAIkD2hQs7IX8f1KrqJnV
24 | 97Dvspfumve2zK+nkTOeJ1tDUKA2zb4kZD5JZWfg2zVkIBd6MA7u4y5lnb26Lvuq
25 | yzuOk/tuQKbH8KTjztWQfNO1b6FZuR/FjRpUYCznSGtjmalbJRYapmEscLxRiOE8
26 | 20inyhgFmgcbGs9tqa9XjojR
27 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.muarine
4 | security
5 | security
6 | war
7 | 1.0
8 | security
9 | http://www.muarine.com
10 |
11 |
12 |
13 | 2.3
14 |
15 |
16 |
17 |
18 |
23 |
24 | commons-codec
25 | commons-codec
26 | 1.10
27 |
28 |
29 |
30 |
31 |
32 |
33 | ROOT
34 |
35 |
36 | maven-compiler-plugin
37 | 3.0
38 |
39 | 1.7
40 | 1.7
41 | true
42 |
43 |
44 |
45 | org.apache.maven.plugins
46 | maven-surefire-plugin
47 | 2.5
48 |
49 |
50 |
51 | **/Test*.java
52 |
53 | true
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/MD5Utils.java:
--------------------------------------------------------------------------------
1 | package com.muarine.security;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.security.MessageDigest;
8 | import java.security.NoSuchAlgorithmException;
9 |
10 | /**
11 | * 说 明 : MD5加密处理工具类
12 | * author: 陆湘星
13 | * data : 2012-12-12
14 | * email : xiangxingchina@163.com
15 | **/
16 |
17 | public class MD5Utils {
18 | /**
19 | * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
20 | */
21 | protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6',
22 | '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
23 |
24 | protected static MessageDigest messagedigest = null;
25 | static {
26 | try {
27 | messagedigest = MessageDigest.getInstance("MD5");
28 | } catch (NoSuchAlgorithmException nsaex) {
29 | System.err.println(MD5Utils.class.getName()
30 | + "初始化失败,MessageDigest不支持MD5Util。");
31 | nsaex.printStackTrace();
32 | }
33 | }
34 |
35 | /**
36 | * 生成字符串的md5校验值
37 | *
38 | * @param s
39 | * @return
40 | */
41 | public static byte[] getMD5String(String s) {
42 | return getMD5Bytes(s.getBytes());
43 | }
44 |
45 | /**
46 | * 生成文件的md5校验值
47 | *
48 | * @param file
49 | * @return
50 | * @throws IOException
51 | */
52 | public static String getFileMD5String(File file) throws IOException {
53 | InputStream fis;
54 | fis = new FileInputStream(file);
55 | byte[] buffer = new byte[1024];
56 | int numRead = 0;
57 | while ((numRead = fis.read(buffer)) > 0) {
58 | messagedigest.update(buffer, 0, numRead);
59 | }
60 | fis.close();
61 | return bufferToHex(messagedigest.digest());
62 | }
63 |
64 | /**
65 | * 生成字节数组的md5校验值
66 | *
67 | * @param s
68 | * @return
69 | */
70 | public static String getMD5String(byte[] bytes) {
71 | messagedigest.update(bytes);
72 | return bufferToHex(messagedigest.digest());
73 | }
74 |
75 | /**
76 | * 生成字节数组的md5校验值
77 | *
78 | * @param s
79 | * @return
80 | */
81 | public static byte[] getMD5Bytes(byte[] bytes) {
82 | messagedigest.update(bytes);
83 | return messagedigest.digest();
84 | }
85 |
86 | private static String bufferToHex(byte bytes[]) {
87 | return bufferToHex(bytes, 0, bytes.length);
88 | }
89 |
90 | private static String bufferToHex(byte bytes[], int m, int n) {
91 | StringBuffer stringbuffer = new StringBuffer(2 * n);
92 | int k = m + n;
93 | for (int l = m; l < k; l++) {
94 | appendHexPair(bytes[l], stringbuffer);
95 | }
96 | return stringbuffer.toString();
97 | }
98 |
99 | private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
100 | char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>>
101 | // 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
102 | char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
103 | stringbuffer.append(c0);
104 | stringbuffer.append(c1);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/Base64Utils.java:
--------------------------------------------------------------------------------
1 | package com.muarine.security;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 |
11 | import org.apache.commons.codec.binary.Base64;
12 |
13 | /**
14 | *
15 | * Base64Utils.
16 | *
17 | * @author Muarine
18 | * @date 2015年7月21日
19 | * @since 2.0
20 | */
21 | public class Base64Utils {
22 |
23 | /**
24 | * 文件读取缓冲区大小
25 | */
26 | private static final int CACHE_SIZE = 1024;
27 |
28 | /**
29 | *
30 | * BASE64字符串解码为二进制数据
31 | *
32 | *
33 | * @param base64
34 | * @return
35 | * @throws Exception
36 | */
37 | public static byte[] decode(String base64) throws Exception {
38 | return new Base64().decode(base64.getBytes());
39 | }
40 |
41 | /**
42 | *
43 | * 二进制数据编码为BASE64字符串
44 | *
45 | *
46 | * @param bytes
47 | * @return
48 | * @throws Exception
49 | */
50 | public static String encode(byte[] bytes) throws Exception {
51 | return new String(new Base64().encode(bytes));
52 | }
53 |
54 | /**
55 | *
56 | * 将文件编码为BASE64字符串
57 | *
58 | *
59 | * 大文件慎用,可能会导致内存溢出
60 | *
61 | *
62 | * @param filePath 文件绝对路径
63 | * @return
64 | * @throws Exception
65 | */
66 | public static String encodeFile(String filePath) throws Exception {
67 | byte[] bytes = fileToByte(filePath);
68 | return encode(bytes);
69 | }
70 |
71 | /**
72 | *
73 | * BASE64字符串转回文件
74 | *
75 | *
76 | * @param filePath 文件绝对路径
77 | * @param base64 编码字符串
78 | * @throws Exception
79 | */
80 | public static void decodeToFile(String filePath, String base64) throws Exception {
81 | byte[] bytes = decode(base64);
82 | byteArrayToFile(bytes, filePath);
83 | }
84 |
85 | /**
86 | *
87 | * 文件转换为二进制数组
88 | *
89 | *
90 | * @param filePath 文件路径
91 | * @return
92 | * @throws Exception
93 | */
94 | public static byte[] fileToByte(String filePath) throws Exception {
95 | byte[] data = new byte[0];
96 | File file = new File(filePath);
97 | if (file.exists()) {
98 | FileInputStream in = new FileInputStream(file);
99 | ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
100 | byte[] cache = new byte[CACHE_SIZE];
101 | int nRead = 0;
102 | while ((nRead = in.read(cache)) != -1) {
103 | out.write(cache, 0, nRead);
104 | out.flush();
105 | }
106 | out.close();
107 | in.close();
108 | data = out.toByteArray();
109 | }
110 | return data;
111 | }
112 |
113 | /**
114 | *
115 | * 二进制数据写文件
116 | *
117 | *
118 | * @param bytes 二进制数据
119 | * @param filePath 文件生成目录
120 | */
121 | public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
122 | InputStream in = new ByteArrayInputStream(bytes);
123 | File destFile = new File(filePath);
124 | if (!destFile.getParentFile().exists()) {
125 | destFile.getParentFile().mkdirs();
126 | }
127 | destFile.createNewFile();
128 | OutputStream out = new FileOutputStream(destFile);
129 | byte[] cache = new byte[CACHE_SIZE];
130 | int nRead = 0;
131 | while ((nRead = in.read(cache)) != -1) {
132 | out.write(cache, 0, nRead);
133 | out.flush();
134 | }
135 | out.close();
136 | in.close();
137 | }
138 |
139 |
140 | }
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/AESUtil.java:
--------------------------------------------------------------------------------
1 | package com.muarine.security;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.security.InvalidKeyException;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.security.SecureRandom;
7 |
8 | import javax.crypto.BadPaddingException;
9 | import javax.crypto.Cipher;
10 | import javax.crypto.IllegalBlockSizeException;
11 | import javax.crypto.KeyGenerator;
12 | import javax.crypto.NoSuchPaddingException;
13 | import javax.crypto.SecretKey;
14 | import javax.crypto.spec.IvParameterSpec;
15 | import javax.crypto.spec.SecretKeySpec;
16 |
17 | import org.apache.commons.codec.binary.Base64;
18 |
19 |
20 | public enum AESUtil {
21 | ;
22 | /**
23 | * 密钥算法
24 | * java6支持56位密钥,bouncycastle支持64位
25 | * */
26 | public static final String KEY_ALGORITHM = "AES";
27 | /**
28 | * 加密/解密算法/工作模式/填充方式
29 | *
30 | * JAVA6 支持PKCS5PADDING填充方式
31 | * Bouncy castle支持PKCS7Padding填充方式
32 | * */
33 | public static final String CIPHER_ALGORITHM="AES/CBC/PKCS5Padding";
34 |
35 | /**
36 | * 生成Key
37 | * FIXME Comment this
38 | *
39 | * @return
40 | * @throws NoSuchAlgorithmException
41 | */
42 | public static SecretKey getSecretKey() throws NoSuchAlgorithmException{
43 |
44 | KeyGenerator generator = KeyGenerator.getInstance(KEY_ALGORITHM);
45 | generator.init(256);
46 | SecretKey key = generator.generateKey();
47 | return key;
48 |
49 | }
50 |
51 | /**
52 | * 生成IV
53 | * FIXME Comment this
54 | *
55 | * @return
56 | */
57 | public static IvParameterSpec getIv(){
58 |
59 | SecureRandom rnd = new SecureRandom();
60 | IvParameterSpec iv = new IvParameterSpec(rnd.generateSeed(16));
61 | return iv;
62 |
63 | }
64 |
65 | /**
66 | *
67 | * 加密
68 | * @param src
69 | * @return
70 | * @throws Exception
71 | */
72 | public static byte[] encrypt(String src , SecretKey k , IvParameterSpec iv) throws Exception{
73 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
74 | cipher.init(Cipher.ENCRYPT_MODE, k, iv);
75 | return cipher.doFinal(src.getBytes());
76 | }
77 |
78 | /**
79 | * 加密
80 | *
81 | * @param content 需要加密的内容
82 | * @param password 加密密码
83 | * @return
84 | */
85 | public static byte[] encrypt(String content, String password) {
86 | try {
87 | KeyGenerator kgen = KeyGenerator.getInstance("AES");
88 | kgen.init(256, new SecureRandom(password.getBytes()));
89 | SecretKey secretKey = kgen.generateKey();
90 | byte[] enCodeFormat = secretKey.getEncoded();
91 | SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
92 | Cipher cipher = Cipher.getInstance("AES");// 创建密码器
93 | byte[] byteContent = content.getBytes("utf-8");
94 | cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
95 | byte[] re = cipher.doFinal(byteContent);
96 |
97 | return re; // 加密
98 | } catch (NoSuchAlgorithmException e) {
99 | e.printStackTrace();
100 | } catch (NoSuchPaddingException e) {
101 | e.printStackTrace();
102 | } catch (InvalidKeyException e) {
103 | e.printStackTrace();
104 | } catch (UnsupportedEncodingException e) {
105 | e.printStackTrace();
106 | } catch (IllegalBlockSizeException e) {
107 | e.printStackTrace();
108 | } catch (BadPaddingException e) {
109 | e.printStackTrace();
110 | }
111 | return null;
112 | }
113 | /**
114 | *
115 | * 解密
116 | * @param src
117 | * @return
118 | */
119 | public static String decrypt(String src , SecretKey k , IvParameterSpec iv) {
120 | String decrypted = "";
121 | try {
122 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
123 | cipher.init(Cipher.DECRYPT_MODE, k, iv);
124 | decrypted = new String(cipher.doFinal(new Base64().decode(src)));
125 | } catch (Exception e) {
126 | throw new RuntimeException(e);
127 | }
128 | return decrypted;
129 | }
130 |
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/java/com/muarine/security/RSAUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @Title: RSAUtils.java
3 | * @Package com.muarine.Auto.rsa
4 | * @Description:
5 | * @author maoyun0903(maoyun0903@163.com)
6 | * @date 2015-6-16 下午09:36:33
7 | * @version V1.0
8 | */
9 | package com.muarine.security;
10 |
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.security.Key;
15 | import java.security.KeyFactory;
16 | import java.security.PrivateKey;
17 | import java.security.PublicKey;
18 | import java.security.Signature;
19 | import java.security.cert.CertificateFactory;
20 | import java.security.cert.X509Certificate;
21 | import java.security.interfaces.RSAPrivateKey;
22 | import java.security.interfaces.RSAPublicKey;
23 | import java.security.spec.PKCS8EncodedKeySpec;
24 | import java.security.spec.X509EncodedKeySpec;
25 | import java.util.HashMap;
26 | import java.util.Map;
27 | import java.util.Random;
28 |
29 | import javax.crypto.Cipher;
30 | import javax.crypto.SecretKey;
31 | import javax.crypto.spec.IvParameterSpec;
32 |
33 | /**
34 | * @ClassName: RSAUtils
35 | * @Description: RSA加密
36 | * @author maoyun0903(maoyun0903@163.com)
37 | * @date 2015-6-16 下午09:36:33
38 | * @version V1.0
39 | */
40 |
41 | public class RSAUtils {
42 |
43 | /**
44 | * RSA加密
45 | */
46 | public static final String KEY_ALGORTHM="RSA";//
47 | /**
48 | * 签名算法
49 | */
50 | public static final String SIGNATURE_ALGORITHM="SHA1withRSA";
51 | // public static final String SIGNATURE_ALGORITHM="NONEwithRSA";
52 | // public static final String SIGNATURE_ALGORITHM="MD5withRSA";
53 |
54 | public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
55 | public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥
56 |
57 | public static void main(String[] args) throws Exception{
58 |
59 | Map map = RSAUtils.initKey();
60 | String publicKey = RSAUtils.getPublicKey(map);
61 | String privateKey = RSAUtils.getPrivateKey(map);
62 | String data = "ABC";
63 |
64 | byte[] en = RSAUtils.encryptByPublicKey(data.getBytes(), publicKey);
65 | System.out.println("密文:" + toHexString(en));
66 | byte[] de = RSAUtils.decryptByPrivateKey(en, privateKey);
67 | System.out.println("解密结果:" + new String(de));
68 |
69 | byte[] enc = RSAUtils.encryptByPrivateKey(data.getBytes(), privateKey);
70 | byte[] dec = RSAUtils.decryptByPublicKey(enc, publicKey);
71 | System.out.println("私钥加密:" + toHexString(enc));
72 | System.out.println("公钥解密:" + new String(dec));
73 | byte[] md5 = MD5Utils.getMD5String(data);
74 | System.out.println("md5:" + md5);
75 | String sign = RSAUtils.sign(md5, privateKey);
76 | boolean flag = RSAUtils.verify(md5, publicKey, sign);
77 | System.out.println("sign签名:" + sign);
78 | System.out.println("校验签名:" + flag);
79 |
80 | // AES 加密解密
81 | // 1. 随机生成 key/iv
82 | SecretKey secretKey = AESUtil.getSecretKey();
83 | IvParameterSpec ivParameterSpec = AESUtil.getIv();
84 | // 2. AES 加密
85 | byte[] aes_en = AESUtil.encrypt(data, secretKey, ivParameterSpec);
86 | String aes_de = AESUtil.decrypt(Base64Utils.encode(aes_en), secretKey, ivParameterSpec);
87 | System.out.println("AES原文:" + data);
88 | System.out.println("AES密文(16进制):" + toHexString(aes_en));
89 | System.out.println("AES解密:" + aes_de);
90 | // 3. key/iv 二进制转十六进制
91 | String key = toHexString(secretKey.getEncoded());
92 | String iv = toHexString(ivParameterSpec.getIV());
93 | // System.out.println("AES key length:" + secretKey.getEncoded().length);
94 | // System.out.println("AES iv length:" + ivParameterSpec.getIV().length);
95 | System.out.println("AES key(16进制):" + key);
96 | // 4. RSA加密十六进制的key和iv
97 | System.out.println("AES key(RSA密文):" + toHexString(RSAUtils.encryptByPublicKey(key.getBytes(), publicKey)));
98 | // System.out.println("AES byte key:" + new String(secretKey.getEncoded()));
99 | System.out.println("AES iv(16进制):" + iv);
100 | System.out.println("AES iv(RSA密文):" + toHexString(RSAUtils.encryptByPublicKey(iv.getBytes(), publicKey)));
101 | // System.out.println("AES byte iv:" + new String(ivParameterSpec.getIV()));
102 |
103 | }
104 |
105 |
106 | /**
107 | * 初始化密钥
108 | * @return
109 | * @throws Exception
110 | */
111 | public static Map initKey()throws Exception{
112 |
113 | KeyFactory keyFactory = KeyFactory.getInstance("RSA");
114 | byte[] encodedKey = input2byte(RSAUtils.class.getResourceAsStream("private_key.pem"));
115 | RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64Utils.decode(new String(encodedKey))));
116 |
117 |
118 | // byte[] encodedKey2 = input2byte(RSAUtils.class.getResourceAsStream("rsa_public_key.pem"));
119 | // KeySpec keySpec = new X509EncodedKeySpec(Base64Utils.decode(new String(encodedKey2)));
120 | // RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
121 |
122 | CertificateFactory certificatefactory=CertificateFactory.getInstance("X.509");
123 | InputStream input = RSAUtils.class.getResourceAsStream("rsa_public_key.pem.crt");
124 | X509Certificate Cert = (X509Certificate)certificatefactory.generateCertificate(input);
125 | RSAPublicKey publicKey = (RSAPublicKey) Cert.getPublicKey();
126 |
127 | // KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
128 | // keyPairGenerator.initialize(1024);
129 | // KeyPair keyPair = keyPairGenerator.generateKeyPair();
130 |
131 | //公钥
132 | // RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
133 | //私钥
134 | // RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
135 |
136 | Map keyMap = new HashMap(2);
137 | keyMap.put(PUBLIC_KEY, publicKey);
138 | keyMap.put(PRIVATE_KEY, privateKey);
139 |
140 | return keyMap;
141 | }
142 |
143 | public static final byte[] input2byte(InputStream inStream) throws IOException {
144 | ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
145 | byte[] buff = new byte[100];
146 | int rc = 0;
147 | while ((rc = inStream.read(buff, 0, 100)) > 0) {
148 | swapStream.write(buff, 0, rc);
149 | }
150 | byte[] in2b = swapStream.toByteArray();
151 | return in2b;
152 | }
153 |
154 |
155 | /**
156 | * 取得公钥,并转化为String类型
157 | * @param keyMap
158 | * @return
159 | * @throws Exception
160 | */
161 | public static String getPublicKey(Map keyMap)throws Exception{
162 | Key key = (Key) keyMap.get(PUBLIC_KEY);
163 | return Coder.encryptBASE64(key.getEncoded());
164 | }
165 |
166 | /**
167 | * 取得私钥,并转化为String类型
168 | * @param keyMap
169 | * @return
170 | * @throws Exception
171 | */
172 | public static String getPrivateKey(Map keyMap) throws Exception{
173 | Key key = (Key) keyMap.get(PRIVATE_KEY);
174 | return Coder.encryptBASE64(key.getEncoded());
175 | }
176 |
177 | /**
178 | * 用私钥加密
179 | * @param data 加密数据
180 | * @param key 密钥
181 | * @return
182 | * @throws Exception
183 | */
184 | public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{
185 | //解密密钥
186 | byte[] keyBytes = Coder.decryptBASE64(key);
187 | //取私钥
188 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
189 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
190 | Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
191 |
192 | //对数据加密
193 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
194 | cipher.init(Cipher.ENCRYPT_MODE, privateKey);
195 |
196 | return cipher.doFinal(data);
197 | }
198 |
199 |
200 | /**
201 | * 用私钥解密 * @param data 加密数据
202 | * @param key 密钥
203 | * @return
204 | * @throws Exception
205 | */
206 | public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
207 | //对私钥解密
208 | byte[] keyBytes = Coder.decryptBASE64(key);
209 |
210 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
211 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
212 | Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
213 | //对数据解密
214 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
215 | cipher.init(Cipher.DECRYPT_MODE, privateKey);
216 |
217 | return cipher.doFinal(data);
218 | }
219 |
220 |
221 | /**
222 | * 用公钥加密
223 | * @param data 加密数据
224 | * @param key 密钥
225 | * @return
226 | * @throws Exception
227 | */
228 | public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
229 | //对公钥解密
230 | byte[] keyBytes = Coder.decryptBASE64(key);
231 | //取公钥
232 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
233 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
234 | Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
235 |
236 | //对数据解密
237 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
238 | cipher.init(Cipher.ENCRYPT_MODE, publicKey);
239 |
240 | return cipher.doFinal(data);
241 | }
242 |
243 |
244 | /**
245 | * 用公钥解密
246 | * @param data 加密数据
247 | * @param key 密钥
248 | * @return
249 | * @throws Exception
250 | */
251 | public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
252 | //对私钥解密
253 | byte[] keyBytes = Coder.decryptBASE64(key);
254 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
255 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
256 | Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
257 |
258 | //对数据解密
259 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
260 | cipher.init(Cipher.DECRYPT_MODE, publicKey);
261 |
262 | return cipher.doFinal(data);
263 | }
264 |
265 |
266 | /**
267 | * 用私钥对信息生成数字签名
268 | * @param data //加密数据
269 | * @param privateKey //私钥
270 | * @return
271 | * @throws Exception
272 | */
273 | public static String sign(byte[] data,String privateKey)throws Exception{
274 | //解密私钥
275 | byte[] keyBytes = Coder.decryptBASE64(privateKey);
276 | //构造PKCS8EncodedKeySpec对象
277 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
278 | //指定加密算法
279 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
280 | //取私钥匙对象
281 | PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
282 | //用私钥对信息生成数字签名
283 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
284 | signature.initSign(privateKey2);
285 | signature.update(data);
286 |
287 | return toHexString(signature.sign());
288 | }
289 |
290 |
291 | /**
292 | * 校验数字签名
293 | * @param data 加密数据
294 | * @param publicKey 公钥
295 | * @param sign 数字签名
296 | * @return
297 | * @throws Exception
298 | */
299 | public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{
300 | //解密公钥
301 | byte[] keyBytes = Coder.decryptBASE64(publicKey);
302 | //构造X509EncodedKeySpec对象
303 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
304 | //指定加密算法
305 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
306 | //取公钥匙对象
307 | PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
308 |
309 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
310 | signature.initVerify(publicKey2);
311 | signature.update(data);
312 | //验证签名是否正常
313 | return signature.verify(toBytes(sign));
314 |
315 | }
316 |
317 | /**
318 | * Md5参数签名
319 | * @param merchantCode
320 | * @param rsa_random_num
321 | * @param rsa_time_flag
322 | * @return String
323 | */
324 | public static byte[] matchKey(String merchantCode, String rsa_random_num,
325 | String rsa_time_flag) {
326 | StringBuffer sb = new StringBuffer();
327 | sb.append("merchantCode=")
328 | .append(merchantCode)
329 | .append("&")
330 | .append("rsa_random_num=")
331 | .append(rsa_random_num)
332 | .append("&")
333 | .append("rsa_time_flag=")
334 | .append(rsa_time_flag);
335 |
336 | return MD5Utils.getMD5String(sb.toString());
337 | }
338 |
339 | /**
340 | * 获取一定长度的随机字符串
341 | * @param length 指定字符串长度
342 | * @return 一定长度的字符串
343 | */
344 | public static String getRandomStringByLength(int length) {
345 | String base = "abcdefghijklmnopqrstuvwxyz0123456789";
346 | Random random = new Random();
347 | StringBuffer sb = new StringBuffer();
348 | for (int i = 0; i < length; i++) {
349 | int number = random.nextInt(base.length());
350 | sb.append(base.charAt(number));
351 | }
352 | return sb.toString();
353 | }
354 |
355 | /**
356 | * 字节数组转十六进制
357 | */
358 | public static String toHexString(byte[] b) {
359 | StringBuilder sb = new StringBuilder(b.length * 2);
360 | for (int i = 0; i < b.length; i++) {
361 | sb.append(HEXCHAR[(b[i] & 0xf0) >>> 4]);
362 | sb.append(HEXCHAR[b[i] & 0x0f]);
363 | }
364 | return sb.toString();
365 | }
366 |
367 | /**
368 | * 十六进制转byte
369 | * FIXME Comment this
370 | *
371 | * @param s
372 | * @return
373 | */
374 | public static final byte[] toBytes(String s) {
375 | byte[] bytes;
376 | bytes = new byte[s.length() / 2];
377 | for (int i = 0; i < bytes.length; i++) {
378 | bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),
379 | 16);
380 | }
381 | return bytes;
382 | }
383 |
384 | private static char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7',
385 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
386 |
387 | }
388 |
--------------------------------------------------------------------------------