├── .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 | --------------------------------------------------------------------------------