├── img ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png └── 8.png ├── web ├── jar │ ├── dom4j-1.6.1.jar │ ├── fastjson-1.2.24.jar │ ├── sun.misc.BASE64Decoder.jar │ └── commons-configuration2-2.1.1.jar ├── AESUtils.java └── RSAUtils.java ├── key ├── rsa_public_key.pem ├── rsa_private_key.pem └── pkcs8_rsa_private_key.pem ├── README.md └── android ├── AESUtils.java └── RSAUtils.java /img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/1.png -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/3.png -------------------------------------------------------------------------------- /img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/4.png -------------------------------------------------------------------------------- /img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/5.png -------------------------------------------------------------------------------- /img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/6.png -------------------------------------------------------------------------------- /img/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/7.png -------------------------------------------------------------------------------- /img/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/img/8.png -------------------------------------------------------------------------------- /web/jar/dom4j-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/web/jar/dom4j-1.6.1.jar -------------------------------------------------------------------------------- /web/jar/fastjson-1.2.24.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/web/jar/fastjson-1.2.24.jar -------------------------------------------------------------------------------- /web/jar/sun.misc.BASE64Decoder.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/web/jar/sun.misc.BASE64Decoder.jar -------------------------------------------------------------------------------- /web/jar/commons-configuration2-2.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxmylife/RSA_AES/HEAD/web/jar/commons-configuration2-2.1.1.jar -------------------------------------------------------------------------------- /key/rsa_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6/WfdPyYTEDII/bw8nyj 3 | hXj74s9Y2A9RboscmQ73IdaBMYeSbgjlmyDTUteQaC5HH9Jn7gF+6XTiSnrvm8jM 4 | hH43izzL26N0PZQP4fAPRG4mvRfjT7eB9e26P854dPIRwI8NfQmgYRKIaPtpaODe 5 | x8lhFXFG4VqQEUVx0O5owKz0wV81ZHwm3L8DCzyP45D4DrmZtQsNi/KOvG2XP7BN 6 | /O3mRmB8mnukdT4jqkQzmy+dYPi/RAHpC8ZYbtSj407RLoaekIKw0wsl3vwTEeaa 7 | 4zUqIVxTotEG2gTAtZUjwcZsIuUtZz0dxtpa14WSLqDzySmWVjxoMD3ZtS7xZEu5 8 | UwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /key/rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA6/WfdPyYTEDII/bw8nyjhXj74s9Y2A9RboscmQ73IdaBMYeS 3 | bgjlmyDTUteQaC5HH9Jn7gF+6XTiSnrvm8jMhH43izzL26N0PZQP4fAPRG4mvRfj 4 | T7eB9e26P854dPIRwI8NfQmgYRKIaPtpaODex8lhFXFG4VqQEUVx0O5owKz0wV81 5 | ZHwm3L8DCzyP45D4DrmZtQsNi/KOvG2XP7BN/O3mRmB8mnukdT4jqkQzmy+dYPi/ 6 | RAHpC8ZYbtSj407RLoaekIKw0wsl3vwTEeaa4zUqIVxTotEG2gTAtZUjwcZsIuUt 7 | Zz0dxtpa14WSLqDzySmWVjxoMD3ZtS7xZEu5UwIDAQABAoIBAE14RlM1f5dBibRt 8 | JiynCVUQJLsR0pyVYuoFWG1UQYVllOM7HLNtzlzBSUCgr7PUxdtHzIGTEiT6EDXd 9 | 6P9fzO4PNpNLca76GncBPrmyhIC2HZfl2ObaXBvvYkACvP/AXl23WflciMB2Qj0d 10 | lj0t31b+4hYVK+1fO3/AKh8rt07SmMFNb/soDCOCx4HY/W3Esv5dqPq1Ru1qZUax 11 | DW+ThW1+CVVD5lwu4GugRKtgUVCpYtV+2F9fTT5hG7M87JppjXd47siWcVA2Nr5L 12 | iR6OpivwkXRAgPT8/5B/vQlAvbPwEdQHzH4XHGaSIv2QB7UzVf+jGZZuh0IGHO/5 13 | NIcCA9ECgYEA/8Ej6gv7dGARxUoj6Nz9VIZFoXbi10KEoqIxVZr2aFPEjO54qE2Y 14 | n5ZO6TEk2+9O9zdDNINWgOXAl+ppij8/ooPw3TC0jkYYpXIRHK6CGkdtykuQ0x9g 15 | 1OIWdCkYcqQja1TzZE1eG/0/HFclLHc1s4mZZR6XS8eqNgQ8moHigJsCgYEA7C+e 16 | Cm/57hA7OgLQA7Xr6+3QAVQChl9+2y7frg773nyELVezV3hVenXe6c/VApeVdmI5 17 | 9qk2IAqI7wVPJ5e7SDXLLy6/tFLedG05TZKRt2PKvJc54ppgl0U2v7SYr/cssk2Z 18 | EjBr9qrF/1EqsECDnWUKF5Jf2+GkWBTD+wJEKakCgYB0FQPqDTo6nggy1e3qmbNa 19 | E/+yw7U+IvD0qE1gH4/L1omVtf+J1H57oMt8SFQEh1/+EVUtlpdCtgVubnUszHxj 20 | lSNUIfExylsRbO6baBGhP95zPU0kpk9bEKtEWgrArgNtigdW9U7LwWxNvrgesJTt 21 | Qn0fSn09Zgi5r76aGm3mFQKBgQDmE9Te0gokMMehUVAV7UgvgnDYemAjSi+nkNfx 22 | FUOijqWsDfz0vpJ2QxCtr/oPFl9Q/Yr9kATb3adbQE7FgPe99jlCc0XogbmWrTff 23 | K2KrxZifcqm+5ygk9BXLVkBPWne+Ef2FTIo/tkg+2XC+VXpg/yZ/o+WhqwOPklr/ 24 | 0EtaUQKBgAUnAMkgfUXT7RTAOZL2foAcM4sbcBiO52iRM2ldZgFTK1IRvtMFNFr3 25 | JbYvHi8tAsUceiEZhzdYpTVSlrVdrqOjwIXmUK3RiOTMkFaYqgPMJighsLcKNRpb 26 | sOdY8rW2A7okN0q4YjvhE2rNoteD+JbJGNB5VE6OC00kCy/KOrT0 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /key/pkcs8_rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDr9Z90/JhMQMgj 3 | 9vDyfKOFePviz1jYD1FuixyZDvch1oExh5JuCOWbINNS15BoLkcf0mfuAX7pdOJK 4 | eu+byMyEfjeLPMvbo3Q9lA/h8A9Ebia9F+NPt4H17bo/znh08hHAjw19CaBhEoho 5 | +2lo4N7HyWEVcUbhWpARRXHQ7mjArPTBXzVkfCbcvwMLPI/jkPgOuZm1Cw2L8o68 6 | bZc/sE387eZGYHyae6R1PiOqRDObL51g+L9EAekLxlhu1KPjTtEuhp6QgrDTCyXe 7 | /BMR5prjNSohXFOi0QbaBMC1lSPBxmwi5S1nPR3G2lrXhZIuoPPJKZZWPGgwPdm1 8 | LvFkS7lTAgMBAAECggEATXhGUzV/l0GJtG0mLKcJVRAkuxHSnJVi6gVYbVRBhWWU 9 | 4zscs23OXMFJQKCvs9TF20fMgZMSJPoQNd3o/1/M7g82k0txrvoadwE+ubKEgLYd 10 | l+XY5tpcG+9iQAK8/8BeXbdZ+VyIwHZCPR2WPS3fVv7iFhUr7V87f8AqHyu3TtKY 11 | wU1v+ygMI4LHgdj9bcSy/l2o+rVG7WplRrENb5OFbX4JVUPmXC7ga6BEq2BRUKli 12 | 1X7YX19NPmEbszzsmmmNd3juyJZxUDY2vkuJHo6mK/CRdECA9Pz/kH+9CUC9s/AR 13 | 1AfMfhccZpIi/ZAHtTNV/6MZlm6HQgYc7/k0hwID0QKBgQD/wSPqC/t0YBHFSiPo 14 | 3P1UhkWhduLXQoSiojFVmvZoU8SM7nioTZiflk7pMSTb7073N0M0g1aA5cCX6mmK 15 | Pz+ig/DdMLSORhilchEcroIaR23KS5DTH2DU4hZ0KRhypCNrVPNkTV4b/T8cVyUs 16 | dzWziZllHpdLx6o2BDyageKAmwKBgQDsL54Kb/nuEDs6AtADtevr7dABVAKGX37b 17 | Lt+uDvvefIQtV7NXeFV6dd7pz9UCl5V2Yjn2qTYgCojvBU8nl7tINcsvLr+0Ut50 18 | bTlNkpG3Y8q8lznimmCXRTa/tJiv9yyyTZkSMGv2qsX/USqwQIOdZQoXkl/b4aRY 19 | FMP7AkQpqQKBgHQVA+oNOjqeCDLV7eqZs1oT/7LDtT4i8PSoTWAfj8vWiZW1/4nU 20 | fnugy3xIVASHX/4RVS2Wl0K2BW5udSzMfGOVI1Qh8THKWxFs7ptoEaE/3nM9TSSm 21 | T1sQq0RaCsCuA22KB1b1TsvBbE2+uB6wlO1CfR9KfT1mCLmvvpoabeYVAoGBAOYT 22 | 1N7SCiQwx6FRUBXtSC+CcNh6YCNKL6eQ1/EVQ6KOpawN/PS+knZDEK2v+g8WX1D9 23 | iv2QBNvdp1tATsWA9732OUJzReiBuZatN98rYqvFmJ9yqb7nKCT0FctWQE9ad74R 24 | /YVMij+2SD7ZcL5VemD/Jn+j5aGrA4+SWv/QS1pRAoGABScAySB9RdPtFMA5kvZ+ 25 | gBwzixtwGI7naJEzaV1mAVMrUhG+0wU0Wvclti8eLy0CxRx6IRmHN1ilNVKWtV2u 26 | o6PAheZQrdGI5MyQVpiqA8wmKCGwtwo1Gluw51jytbYDuiQ3SrhiO+ETas2i14P4 27 | lskY0HlUTo4LTSQLL8o6tPQ= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 移动端和WEB端的混合加密(RSA和AES) 2 | ******** 3 | 4 | 5 | ## 流程 6 | 是先由服务器创建RSA密钥对,RSA公钥保存在安卓的so文件里面,服务器保存RSA私钥。而安卓创建AES密钥(这个密钥也是在so文件里面),并用该AES密钥加密待传送的明文数据,同时用接受的RSA公钥加密AES密钥,最后把用RSA公钥加密后的AES密钥同密文一起通过Internet传输发送到服务器。当服务器收到这个被加密的AES密钥和密文后,首先调用服务器保存的RSA私钥,并用该私钥解密加密的AES密钥,得到AES密钥。最后用该AES密钥解密密文得到明文 7 | 8 | ![数据加密流程](https://github.com/wxmylife/RSA_AES/blob/master/img/1.png) 9 | 10 | 11 | 12 | #### 推荐文章 13 | [Android数据加密方案](http://www.jianshu.com/p/d4fee3a2de82) 14 | 15 | [Android数据加密之RSA加密](http://www.cnblogs.com/whoislcj/p/5470095.html) 16 | 17 | [Android数据加密之Aes加密](http://www.cnblogs.com/whoislcj/p/5473030.html) 18 | ## 制作RSA公钥和私钥 19 | * 新建一文件夹,用终端进入到该文件夹下 20 | 21 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/2.png) 22 | 23 | * 打开mac自带的OpenSSL 24 | 25 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/3.png) 26 | 27 | * 通过如下命令生成私钥:`genrsa -out rsa_private_key.pem 2048`,生成了一份私钥,加密长度是2048位, 密钥长度,范围:512~2048, 内容是标准的ASCII字符 28 | 29 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/4.png) 30 | 31 | * 通过如下命令生成公钥: 32 | 33 | `rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout` 34 | 35 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/5.png) 36 | 37 | * 这样密钥就基本生成了,不过这样密钥对的私钥是无法在代码中直接使用的,要想使用它需要借助RSAPrivateKeyStructure这个类,Java是不自带的。所以为了方便使用,我们需要对私钥进行PKCS#8编码,命令如下: 38 | 39 | `pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt` 40 | 41 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/6.png) 42 | 43 | * 所有步骤完成,最终如下图 44 | 45 | ![效果示例](https://github.com/wxmylife/RSA_AES/blob/master/img/7.png) 46 | *** 47 | ## 测试代码 48 | ``` 49 | //得到AES加密随机生成的密钥匙 50 | String aesKey= AESUtils.generateKeyString(); 51 | System.out.println("AES秘钥为-------->>>>"+aesKey); 52 | System.out.println("<<<<---------------------------------------->>>>"); 53 | //获取加密数据 54 | String context=initData(); 55 | 56 | //AES加密生成密文 57 | String aesToContext=AESUtils.encrypt(context, aesKey); 58 | System.out.println("AES加密后密文为-------->>>>"+aesToContext); 59 | System.out.println("<<<<---------------------------------------->>>>"); 60 | //获取RSA公钥 61 | RSAPublicKey publicKey=RSAUtils.loadPublicKey(new FileInputStream("rsa_public_key.pem文件路径")); 62 | //RSA公钥加密AES生成的密钥匙 63 | String rsaAesKey=RSAUtils.encryptByPublicKey(aesKey, publicKey); 64 | System.out.println("RSA加密后密钥为-------->>>>"+rsaAesKey); 65 | 66 | 67 | 68 | System.out.println("<<<<---------------------------------------->>>>"); 69 | //获取RSA私钥路径 70 | RSAPrivateKey privateKey=RSAUtils.loadPrivateKey(new FileInputStream("pkcs8_rsa_private_key.pem文件路径")); 71 | //RSA私钥解密加密过后的AES生成的密钥匙 72 | String aesRKey=RSAUtils.decryptByPrivateKey(rsaAesKey, privateKey); 73 | System.out.println("RSA解密后密钥为-------->>>>"+aesRKey); 74 | String txt=AESUtils.decrypt(aesToContext, aesRKey); 75 | System.out.println("AES解密后密文为-------->>>>"+txt);``` 76 | -------------------------------------------------------------------------------- /web/AESUtils.java: -------------------------------------------------------------------------------- 1 | package com.wxmylife.tools.utils; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.SecureRandom; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.KeyGenerator; 9 | import javax.crypto.SecretKey; 10 | import javax.crypto.spec.SecretKeySpec; 11 | 12 | public class AESUtils { 13 | 14 | 15 | // /** 算法/模式/填充 **/ 16 | private static final String CipherMode = "AES/ECB/PKCS5Padding"; 17 | // private static final String CipherMode = "AES"; 18 | 19 | /** 20 | * 生成一个AES密钥对象 21 | * @return 22 | */ 23 | public static SecretKeySpec generateKey(){ 24 | try { 25 | KeyGenerator kgen = KeyGenerator.getInstance("AES"); 26 | kgen.init(128, new SecureRandom()); 27 | SecretKey secretKey = kgen.generateKey(); 28 | byte[] enCodeFormat = secretKey.getEncoded(); 29 | SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); 30 | return key; 31 | } catch (NoSuchAlgorithmException e) { 32 | e.printStackTrace(); 33 | } 34 | return null; 35 | } 36 | 37 | /** 38 | * 生成一个AES密钥字符串 39 | * @return 40 | */ 41 | public static String generateKeyString(){ 42 | return byte2hex(generateKey().getEncoded()); 43 | } 44 | 45 | /** 46 | * 加密字节数据 47 | * @param content 48 | * @param key 49 | * @return 50 | */ 51 | public static byte[] encrypt(byte[] content,byte[] key) { 52 | try { 53 | Cipher cipher = Cipher.getInstance(CipherMode); 54 | cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); 55 | byte[] result = cipher.doFinal(content); 56 | return result; 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | } 60 | return null; 61 | } 62 | 63 | /** 64 | * 通过byte[]类型的密钥加密String 65 | * @param content 66 | * @param key 67 | * @return 16进制密文字符串 68 | */ 69 | public static String encrypt(String content,byte[] key) { 70 | try { 71 | Cipher cipher = Cipher.getInstance(CipherMode); 72 | cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); 73 | byte[] data = cipher.doFinal(content.getBytes("UTF-8")); 74 | String result = byte2hex(data); 75 | return result; 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | return null; 80 | } 81 | 82 | /** 83 | * 通过String类型的密钥加密String 84 | * @param content 85 | * @param key 86 | * @return 16进制密文字符串 87 | */ 88 | public static String encrypt(String content,String key) { 89 | byte[] data = null; 90 | try { 91 | data = content.getBytes("UTF-8"); 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded()); 96 | String result = byte2hex(data); 97 | return result; 98 | } 99 | 100 | /** 101 | * 通过byte[]类型的密钥解密byte[] 102 | * @param content 103 | * @param key 104 | * @return 105 | */ 106 | public static byte[] decrypt(byte[] content,byte[] key) { 107 | try { 108 | Cipher cipher = Cipher.getInstance(CipherMode); 109 | cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES")); 110 | byte[] result = cipher.doFinal(content); 111 | return result; 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | } 115 | return null; 116 | } 117 | 118 | /** 119 | * 通过String类型的密钥 解密String类型的密文 120 | * @param content 121 | * @param key 122 | * @return 123 | */ 124 | public static String decrypt(String content, String key) { 125 | byte[] data = null; 126 | try { 127 | data = hex2byte(content); 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | } 131 | data = decrypt(data, hex2byte(key)); 132 | if (data == null) 133 | return null; 134 | String result = null; 135 | try { 136 | result = new String(data, "UTF-8"); 137 | } catch (UnsupportedEncodingException e) { 138 | e.printStackTrace(); 139 | } 140 | return result; 141 | } 142 | 143 | /** 144 | * 通过byte[]类型的密钥 解密String类型的密文 145 | * @param content 146 | * @param key 147 | * @return 148 | */ 149 | public static String decrypt(String content,byte[] key) { 150 | try { 151 | Cipher cipher = Cipher.getInstance(CipherMode); 152 | cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES")); 153 | byte[] data = cipher.doFinal(hex2byte(content)); 154 | return new String(data, "UTF-8"); 155 | } catch (Exception e) { 156 | e.printStackTrace(); 157 | } 158 | return null; 159 | } 160 | 161 | /** 162 | * 字节数组转成16进制字符串 163 | * @param b 164 | * @return 165 | */ 166 | public static String byte2hex(byte[] b) { // 一个字节的数, 167 | StringBuffer sb = new StringBuffer(b.length * 2); 168 | String tmp = ""; 169 | for (int n = 0; n < b.length; n++) { 170 | // 整数转成十六进制表示 171 | tmp = (Integer.toHexString(b[n] & 0XFF)); 172 | if (tmp.length() == 1) { 173 | sb.append("0"); 174 | } 175 | sb.append(tmp); 176 | } 177 | return sb.toString().toUpperCase(); // 转成大写 178 | } 179 | 180 | /** 181 | * 将hex字符串转换成字节数组 182 | * @param inputString 183 | * @return 184 | */ 185 | private static byte[] hex2byte(String inputString) { 186 | if (inputString == null || inputString.length() < 2) { 187 | return new byte[0]; 188 | } 189 | inputString = inputString.toLowerCase(); 190 | int l = inputString.length() / 2; 191 | byte[] result = new byte[l]; 192 | for (int i = 0; i < l; ++i) { 193 | String tmp = inputString.substring(2 * i, 2 * i + 2); 194 | result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); 195 | } 196 | return result; 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /android /AESUtils.java: -------------------------------------------------------------------------------- 1 | package cn.boruihy.qunawancustomer.ui.test; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.SecureRandom; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.KeyGenerator; 9 | import javax.crypto.SecretKey; 10 | import javax.crypto.spec.SecretKeySpec; 11 | 12 | public class AESUtils { 13 | // /** 算法/模式/填充 **/ 14 | private static final String CipherMode = "AES/ECB/PKCS5Padding"; 15 | // private static final String CipherMode = "AES"; 16 | 17 | /** 18 | * 生成一个AES密钥对象 19 | * @return 20 | */ 21 | public static SecretKeySpec generateKey(){ 22 | try { 23 | KeyGenerator kgen = KeyGenerator.getInstance("AES"); 24 | kgen.init(128, new SecureRandom()); 25 | SecretKey secretKey = kgen.generateKey(); 26 | byte[] enCodeFormat = secretKey.getEncoded(); 27 | SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); 28 | return key; 29 | } catch (NoSuchAlgorithmException e) { 30 | e.printStackTrace(); 31 | } 32 | return null; 33 | } 34 | 35 | /** 36 | * 生成一个AES密钥字符串 37 | * @return 38 | */ 39 | public static String generateKeyString(){ 40 | return byte2hex(generateKey().getEncoded()); 41 | } 42 | 43 | /** 44 | * 加密字节数据 45 | * @param content 46 | * @param key 47 | * @return 48 | */ 49 | public static byte[] encrypt(byte[] content,byte[] key) { 50 | try { 51 | Cipher cipher = Cipher.getInstance(CipherMode); 52 | cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); 53 | byte[] result = cipher.doFinal(content); 54 | return result; 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | return null; 59 | } 60 | 61 | /** 62 | * 通过byte[]类型的密钥加密String 63 | * @param content 64 | * @param key 65 | * @return 16进制密文字符串 66 | */ 67 | public static String encrypt(String content,byte[] key) { 68 | try { 69 | Cipher cipher = Cipher.getInstance(CipherMode); 70 | cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); 71 | byte[] data = cipher.doFinal(content.getBytes("UTF-8")); 72 | String result = byte2hex(data); 73 | return result; 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | } 77 | return null; 78 | } 79 | 80 | /** 81 | * 通过String类型的密钥加密String 82 | * @param content 83 | * @param key 84 | * @return 16进制密文字符串 85 | */ 86 | public static String encrypt(String content,String key) { 87 | byte[] data = null; 88 | try { 89 | data = content.getBytes("UTF-8"); 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | } 93 | data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded()); 94 | String result = byte2hex(data); 95 | return result; 96 | } 97 | 98 | /** 99 | * 通过byte[]类型的密钥解密byte[] 100 | * @param content 101 | * @param key 102 | * @return 103 | */ 104 | public static byte[] decrypt(byte[] content,byte[] key) { 105 | try { 106 | Cipher cipher = Cipher.getInstance(CipherMode); 107 | cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES")); 108 | byte[] result = cipher.doFinal(content); 109 | return result; 110 | } catch (Exception e) { 111 | e.printStackTrace(); 112 | } 113 | return null; 114 | } 115 | 116 | /** 117 | * 通过String类型的密钥 解密String类型的密文 118 | * @param content 119 | * @param key 120 | * @return 121 | */ 122 | public static String decrypt(String content, String key) { 123 | byte[] data = null; 124 | try { 125 | data = hex2byte(content); 126 | } catch (Exception e) { 127 | e.printStackTrace(); 128 | } 129 | data = decrypt(data, hex2byte(key)); 130 | if (data == null) 131 | return null; 132 | String result = null; 133 | try { 134 | result = new String(data, "UTF-8"); 135 | } catch (UnsupportedEncodingException e) { 136 | e.printStackTrace(); 137 | } 138 | return result; 139 | } 140 | 141 | /** 142 | * 通过byte[]类型的密钥 解密String类型的密文 143 | * @param content 144 | * @param key 145 | * @return 146 | */ 147 | public static String decrypt(String content,byte[] key) { 148 | try { 149 | Cipher cipher = Cipher.getInstance(CipherMode); 150 | cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES")); 151 | byte[] data = cipher.doFinal(hex2byte(content)); 152 | return new String(data, "UTF-8"); 153 | } catch (Exception e) { 154 | e.printStackTrace(); 155 | } 156 | return null; 157 | } 158 | 159 | /** 160 | * 字节数组转成16进制字符串 161 | * @param b 162 | * @return 163 | */ 164 | public static String byte2hex(byte[] b) { // 一个字节的数, 165 | StringBuffer sb = new StringBuffer(b.length * 2); 166 | String tmp = ""; 167 | for (int n = 0; n < b.length; n++) { 168 | // 整数转成十六进制表示 169 | tmp = (Integer.toHexString(b[n] & 0XFF)); 170 | if (tmp.length() == 1) { 171 | sb.append("0"); 172 | } 173 | sb.append(tmp); 174 | } 175 | return sb.toString().toUpperCase(); // 转成大写 176 | } 177 | 178 | /** 179 | * 将hex字符串转换成字节数组 180 | * @param inputString 181 | * @return 182 | */ 183 | private static byte[] hex2byte(String inputString) { 184 | if (inputString == null || inputString.length() < 2) { 185 | return new byte[0]; 186 | } 187 | inputString = inputString.toLowerCase(); 188 | int l = inputString.length() / 2; 189 | byte[] result = new byte[l]; 190 | for (int i = 0; i < l; ++i) { 191 | String tmp = inputString.substring(2 * i, 2 * i + 2); 192 | result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); 193 | } 194 | return result; 195 | } 196 | 197 | 198 | } 199 | -------------------------------------------------------------------------------- /android /RSAUtils.java: -------------------------------------------------------------------------------- 1 | package cn.boruihy.qunawancustomer.ui.test; 2 | 3 | import android.util.Base64; 4 | import java.io.BufferedReader; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.security.KeyFactory; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.security.interfaces.RSAPrivateKey; 11 | import java.security.interfaces.RSAPublicKey; 12 | import java.security.spec.InvalidKeySpecException; 13 | import java.security.spec.PKCS8EncodedKeySpec; 14 | import java.security.spec.X509EncodedKeySpec; 15 | import javax.crypto.Cipher; 16 | 17 | 18 | 19 | public class RSAUtils { 20 | private static final String ALGORITHM = "RSA"; 21 | private static final String TRANSFORMATION = "RSA"; 22 | 23 | /** 24 | * 从文件中输入流中加载公钥 25 | * 26 | * @param in 27 | * 公钥输入流 28 | * @throws Exception 29 | * 加载公钥时产生的异常 30 | */ 31 | public static RSAPublicKey loadPublicKey(InputStream in) throws Exception { 32 | try { 33 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 34 | String readLine = null; 35 | StringBuilder sb = new StringBuilder(); 36 | while ((readLine = br.readLine()) != null) { 37 | if (readLine.charAt(0) == '-') { 38 | continue; 39 | } else { 40 | sb.append(readLine); 41 | sb.append('\r'); 42 | } 43 | } 44 | return loadPublicKey(sb.toString()); 45 | } catch (IOException e) { 46 | throw new Exception("公钥数据流读取错误"); 47 | } catch (NullPointerException e) { 48 | throw new Exception("公钥输入流为空"); 49 | } 50 | } 51 | 52 | /** 53 | * 从字符串中加载公钥 54 | * 55 | * @param publicKeyStr 56 | * 公钥数据字符串 57 | * @return 58 | * @throws Exception 59 | * 加载公钥时产生的异常 60 | */ 61 | public static RSAPublicKey loadPublicKey(String publicKeyStr) 62 | throws Exception { 63 | try { 64 | byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT); 65 | KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 66 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); 67 | return (RSAPublicKey) keyFactory.generatePublic(keySpec); 68 | } catch (NoSuchAlgorithmException e) { 69 | throw new Exception("无此算法"); 70 | } catch (InvalidKeySpecException e) { 71 | throw new Exception("公钥非法"); 72 | }catch (NullPointerException e) { 73 | throw new Exception("公钥数据为空"); 74 | } 75 | } 76 | 77 | /** 78 | * 从文件中加载私钥 79 | * 80 | * @param in 81 | * 私钥输入流 82 | * @return 83 | * @throws Exception 84 | */ 85 | public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception { 86 | try { 87 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 88 | String readLine = null; 89 | StringBuilder sb = new StringBuilder(); 90 | while ((readLine = br.readLine()) != null) { 91 | if (readLine.charAt(0) == '-') { 92 | continue; 93 | } else { 94 | sb.append(readLine); 95 | sb.append('\r'); 96 | } 97 | } 98 | return loadPrivateKey(sb.toString()); 99 | } catch (IOException e) { 100 | throw new Exception("私钥数据读取错误"); 101 | } catch (NullPointerException e) { 102 | throw new Exception("私钥输入流为空"); 103 | } 104 | } 105 | 106 | /** 107 | * 从字符串中加载私钥 108 | * 109 | * @desc 110 | * @param privateKeyStr 111 | * 私钥字符串 112 | * @return 113 | * @throws Exception 114 | */ 115 | public static RSAPrivateKey loadPrivateKey(String privateKeyStr) 116 | throws Exception { 117 | try { 118 | byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT); 119 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); 120 | KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 121 | return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); 122 | } catch (NoSuchAlgorithmException e) { 123 | throw new Exception("无此算法"); 124 | } catch (InvalidKeySpecException e) { 125 | throw new Exception("私钥非法"); 126 | }catch (NullPointerException e) { 127 | throw new Exception("私钥数据为空"); 128 | } 129 | } 130 | 131 | /** 132 | * 公钥加密 133 | * 134 | * @param data 135 | * @param publicKey 136 | * @return 137 | * @throws Exception 138 | */ 139 | public static String encryptByPublicKey(String data, RSAPublicKey publicKey) 140 | throws Exception { 141 | // 模长 142 | int key_len = publicKey.getModulus().bitLength() / 8; 143 | // 加密数据长度 <= 模长-11 144 | String[] datas = splitString(data, key_len - 11); 145 | String mi = ""; 146 | // 如果明文长度大于模长-11则要分组加密 147 | for (String s : datas) { 148 | mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey)); 149 | } 150 | return mi; 151 | } 152 | 153 | /** 154 | * 公钥加密 155 | * @desc 156 | * @param data 157 | * @param publicKey 158 | * @return 159 | * @throws Exception 160 | */ 161 | public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) 162 | throws Exception { 163 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 164 | cipher.init(Cipher.ENCRYPT_MODE, publicKey); 165 | return cipher.doFinal(data); 166 | } 167 | 168 | /** 169 | * 私钥加密 170 | * @desc 171 | * @param data 172 | * @param privateKey 173 | * @return 174 | * @throws Exception 175 | */ 176 | public static byte[] encryptByPrivateKey(byte[] data, 177 | RSAPrivateKey privateKey) throws Exception { 178 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 179 | cipher.init(Cipher.ENCRYPT_MODE, privateKey); 180 | return cipher.doFinal(data); 181 | } 182 | 183 | 184 | /** 185 | * 私钥加密 186 | * @desc 187 | * @param data 188 | * @param privateKey 189 | * @return 190 | * @throws Exception 191 | */ 192 | public static String encryptByPrivateKey(String data, 193 | RSAPrivateKey privateKey) throws Exception { 194 | // 模长 195 | int key_len = privateKey.getModulus().bitLength() / 8; 196 | // 加密数据长度 <= 模长-11 197 | String[] datas = splitString(data, key_len - 11); 198 | String mi = ""; 199 | // 如果明文长度大于模长-11则要分组加密 200 | for (String s : datas) { 201 | mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey)); 202 | } 203 | return mi; 204 | } 205 | 206 | /** 207 | * 私钥解密 208 | * 209 | * @param data 210 | * @param privateKey 211 | * @return 212 | * @throws Exception 213 | */ 214 | public static String decryptByPrivateKey(String data, 215 | RSAPrivateKey privateKey) throws Exception { 216 | // 模长 217 | int key_len = privateKey.getModulus().bitLength() / 8; 218 | byte[] bytes = data.getBytes(); 219 | byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 220 | // 如果密文长度大于模长则要分组解密 221 | String ming = ""; 222 | byte[][] arrays = splitArray(bcd, key_len); 223 | for (byte[] arr : arrays) { 224 | ming += new String(decryptByPrivateKey(arr, privateKey)); 225 | } 226 | return ming; 227 | } 228 | 229 | /** 230 | * 私钥解密 231 | * @desc 232 | * @param data 233 | * @param privateKey 234 | * @return 235 | * @throws Exception 236 | */ 237 | public static byte[] decryptByPrivateKey(byte[] data, 238 | RSAPrivateKey privateKey) throws Exception { 239 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 240 | cipher.init(Cipher.DECRYPT_MODE, privateKey); 241 | return cipher.doFinal(data); 242 | } 243 | 244 | /** 245 | * 公钥解密 246 | * @desc 247 | * @param data 248 | * @param publicKey 249 | * @return 250 | * @throws Exception 251 | */ 252 | public static String decryptByPublicKey(String data, 253 | RSAPublicKey publicKey) throws Exception { 254 | // 模长 255 | int key_len = publicKey.getModulus().bitLength() / 8; 256 | byte[] bytes = data.getBytes(); 257 | byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 258 | // 如果密文长度大于模长则要分组解密 259 | String ming = ""; 260 | byte[][] arrays = splitArray(bcd, key_len); 261 | for (byte[] arr : arrays) { 262 | ming += new String(decryptByPublicKey(arr, publicKey)); 263 | } 264 | return ming; 265 | } 266 | 267 | /** 268 | * 公钥解密 269 | * @desc 270 | * @param data 271 | * @param publicKey 272 | * @return 273 | * @throws Exception 274 | */ 275 | public static byte[] decryptByPublicKey(byte[] data, 276 | RSAPublicKey publicKey) throws Exception { 277 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 278 | cipher.init(Cipher.DECRYPT_MODE, publicKey); 279 | return cipher.doFinal(data); 280 | } 281 | 282 | /** 283 | * ASCII码转BCD码 284 | * 285 | */ 286 | private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) { 287 | byte[] bcd = new byte[asc_len / 2]; 288 | int j = 0; 289 | for (int i = 0; i < (asc_len + 1) / 2; i++) { 290 | bcd[i] = asc_to_bcd(ascii[j++]); 291 | bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4)); 292 | } 293 | return bcd; 294 | } 295 | 296 | private static byte asc_to_bcd(byte asc) { 297 | byte bcd; 298 | 299 | if ((asc >= '0') && (asc <= '9')) 300 | bcd = (byte) (asc - '0'); 301 | else if ((asc >= 'A') && (asc <= 'F')) 302 | bcd = (byte) (asc - 'A' + 10); 303 | else if ((asc >= 'a') && (asc <= 'f')) 304 | bcd = (byte) (asc - 'a' + 10); 305 | else 306 | bcd = (byte) (asc - 48); 307 | return bcd; 308 | } 309 | 310 | /** 311 | * BCD转字符串 312 | */ 313 | private static String bcd2Str(byte[] bytes) { 314 | char temp[] = new char[bytes.length * 2], val; 315 | 316 | for (int i = 0; i < bytes.length; i++) { 317 | val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f); 318 | temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 319 | 320 | val = (char) (bytes[i] & 0x0f); 321 | temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 322 | } 323 | return new String(temp); 324 | } 325 | 326 | /** 327 | * 拆分字符串 328 | */ 329 | private static String[] splitString(String string, int len) { 330 | int x = string.length() / len; 331 | int y = string.length() % len; 332 | int z = 0; 333 | if (y != 0) { 334 | z = 1; 335 | } 336 | String[] strings = new String[x + z]; 337 | String str = ""; 338 | for (int i = 0; i < x + z; i++) { 339 | if (i == x + z - 1 && y != 0) { 340 | str = string.substring(i * len, i * len + y); 341 | } else { 342 | str = string.substring(i * len, i * len + len); 343 | } 344 | strings[i] = str; 345 | } 346 | return strings; 347 | } 348 | 349 | /** 350 | * 拆分数组 351 | */ 352 | private static byte[][] splitArray(byte[] data, int len) { 353 | int x = data.length / len; 354 | int y = data.length % len; 355 | int z = 0; 356 | if (y != 0) { 357 | z = 1; 358 | } 359 | byte[][] arrays = new byte[x + z][]; 360 | byte[] arr; 361 | for (int i = 0; i < x + z; i++) { 362 | arr = new byte[len]; 363 | if (i == x + z - 1 && y != 0) { 364 | System.arraycopy(data, i * len, arr, 0, y); 365 | } else { 366 | System.arraycopy(data, i * len, arr, 0, len); 367 | } 368 | arrays[i] = arr; 369 | } 370 | return arrays; 371 | } 372 | 373 | 374 | } 375 | -------------------------------------------------------------------------------- /web/RSAUtils.java: -------------------------------------------------------------------------------- 1 | package com.wxmylife.tools.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.security.KeyFactory; 8 | import java.security.NoSuchAlgorithmException; 9 | import java.security.interfaces.RSAPrivateKey; 10 | import java.security.interfaces.RSAPublicKey; 11 | import java.security.spec.InvalidKeySpecException; 12 | import java.security.spec.PKCS8EncodedKeySpec; 13 | import java.security.spec.X509EncodedKeySpec; 14 | 15 | import javax.crypto.Cipher; 16 | 17 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 18 | 19 | import Decoder.BASE64Decoder; 20 | 21 | public class RSAUtils { 22 | private static final String ALGORITHM = "RSA"; 23 | private static final String TRANSFORMATION = "RSA"; 24 | 25 | /** 26 | * 从文件中输入流中加载公钥 27 | * 28 | * @param in 29 | * 公钥输入流 30 | * @throws Exception 31 | * 加载公钥时产生的异常 32 | */ 33 | public static RSAPublicKey loadPublicKey(InputStream in) throws Exception { 34 | try { 35 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 36 | String readLine = null; 37 | StringBuilder sb = new StringBuilder(); 38 | while ((readLine = br.readLine()) != null) { 39 | if (readLine.charAt(0) == '-') { 40 | continue; 41 | } else { 42 | sb.append(readLine); 43 | sb.append('\r'); 44 | } 45 | } 46 | return loadPublicKey(sb.toString()); 47 | } catch (IOException e) { 48 | throw new Exception("公钥数据流读取错误"); 49 | } catch (NullPointerException e) { 50 | throw new Exception("公钥输入流为空"); 51 | } 52 | } 53 | 54 | /** 55 | * 从字符串中加载公钥 56 | * 57 | * @param publicKeyStr 58 | * 公钥数据字符串 59 | * @return 60 | * @throws Exception 61 | * 加载公钥时产生的异常 62 | */ 63 | public static RSAPublicKey loadPublicKey(String publicKeyStr) 64 | throws Exception { 65 | try { 66 | BASE64Decoder base64Decoder = new BASE64Decoder(); 67 | byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr); 68 | KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 69 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); 70 | return (RSAPublicKey) keyFactory.generatePublic(keySpec); 71 | } catch (NoSuchAlgorithmException e) { 72 | throw new Exception("无此算法"); 73 | } catch (InvalidKeySpecException e) { 74 | throw new Exception("公钥非法"); 75 | } catch (IOException e) { 76 | throw new Exception("公钥数据内容读取错误"); 77 | } catch (NullPointerException e) { 78 | throw new Exception("公钥数据为空"); 79 | } 80 | } 81 | 82 | /** 83 | * 从文件中加载私钥 84 | * 85 | * @param in 86 | * 私钥输入流 87 | * @return 88 | * @throws Exception 89 | */ 90 | public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception { 91 | try { 92 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 93 | String readLine = null; 94 | StringBuilder sb = new StringBuilder(); 95 | while ((readLine = br.readLine()) != null) { 96 | if (readLine.charAt(0) == '-') { 97 | continue; 98 | } else { 99 | sb.append(readLine); 100 | sb.append('\r'); 101 | } 102 | } 103 | return loadPrivateKey(sb.toString()); 104 | } catch (IOException e) { 105 | throw new Exception("私钥数据读取错误"); 106 | } catch (NullPointerException e) { 107 | throw new Exception("私钥输入流为空"); 108 | } 109 | } 110 | 111 | /** 112 | * 从字符串中加载私钥 113 | * 114 | * @desc 115 | * @param privateKeyStr 116 | * 私钥字符串 117 | * @return 118 | * @throws Exception 119 | */ 120 | public static RSAPrivateKey loadPrivateKey(String privateKeyStr) 121 | throws Exception { 122 | try { 123 | BASE64Decoder base64Decoder = new BASE64Decoder(); 124 | byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr); 125 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); 126 | KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 127 | return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); 128 | } catch (NoSuchAlgorithmException e) { 129 | throw new Exception("无此算法"); 130 | } catch (InvalidKeySpecException e) { 131 | throw new Exception("私钥非法"); 132 | } catch (IOException e) { 133 | throw new Exception("私钥数据内容读取错误"); 134 | } catch (NullPointerException e) { 135 | throw new Exception("私钥数据为空"); 136 | } 137 | } 138 | 139 | /** 140 | * 公钥加密 141 | * 142 | * @param data 143 | * @param publicKey 144 | * @return 145 | * @throws Exception 146 | */ 147 | public static String encryptByPublicKey(String data, RSAPublicKey publicKey) 148 | throws Exception { 149 | // 模长 150 | int key_len = publicKey.getModulus().bitLength() / 8; 151 | // 加密数据长度 <= 模长-11 152 | String[] datas = splitString(data, key_len - 11); 153 | String mi = ""; 154 | // 如果明文长度大于模长-11则要分组加密 155 | for (String s : datas) { 156 | mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey)); 157 | } 158 | return mi; 159 | } 160 | 161 | /** 162 | * 公钥加密 163 | * @desc 164 | * @param data 165 | * @param publicKey 166 | * @return 167 | * @throws Exception 168 | */ 169 | public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) 170 | throws Exception { 171 | Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider()); 172 | cipher.init(Cipher.ENCRYPT_MODE, publicKey); 173 | return cipher.doFinal(data); 174 | } 175 | 176 | /** 177 | * 私钥加密 178 | * @desc 179 | * @param data 180 | * @param privateKey 181 | * @return 182 | * @throws Exception 183 | */ 184 | public static byte[] encryptByPrivateKey(byte[] data, 185 | RSAPrivateKey privateKey) throws Exception { 186 | Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider()); 187 | cipher.init(Cipher.ENCRYPT_MODE, privateKey); 188 | return cipher.doFinal(data); 189 | } 190 | 191 | /** 192 | * 私钥加密 193 | * @desc 194 | * @param data 195 | * @param privateKey 196 | * @return 197 | * @throws Exception 198 | */ 199 | public static String encryptByPrivateKey(String data, 200 | RSAPrivateKey privateKey) throws Exception { 201 | // 模长 202 | int key_len = privateKey.getModulus().bitLength() / 8; 203 | // 加密数据长度 <= 模长-11 204 | String[] datas = splitString(data, key_len - 11); 205 | String mi = ""; 206 | // 如果明文长度大于模长-11则要分组加密 207 | for (String s : datas) { 208 | mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey)); 209 | } 210 | return mi; 211 | } 212 | 213 | /** 214 | * 私钥解密 215 | * 216 | * @param data 217 | * @param privateKey 218 | * @return 219 | * @throws Exception 220 | */ 221 | public static String decryptByPrivateKey(String data, 222 | RSAPrivateKey privateKey) throws Exception { 223 | // 模长 224 | int key_len = privateKey.getModulus().bitLength() / 8; 225 | byte[] bytes = data.getBytes(); 226 | byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 227 | // 如果密文长度大于模长则要分组解密 228 | String ming = ""; 229 | byte[][] arrays = splitArray(bcd, key_len); 230 | for (byte[] arr : arrays) { 231 | ming += new String(decryptByPrivateKey(arr, privateKey)); 232 | } 233 | return ming; 234 | } 235 | 236 | /** 237 | * 私钥解密 238 | * @desc 239 | * @param data 240 | * @param privateKey 241 | * @return 242 | * @throws Exception 243 | */ 244 | public static byte[] decryptByPrivateKey(byte[] data, 245 | RSAPrivateKey privateKey) throws Exception { 246 | Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider()); 247 | cipher.init(Cipher.DECRYPT_MODE, privateKey); 248 | return cipher.doFinal(data); 249 | } 250 | 251 | /** 252 | * 公钥解密 253 | * @desc 254 | * @param data 255 | * @param publicKey 256 | * @return 257 | * @throws Exception 258 | */ 259 | public static String decryptByPublicKey(String data, 260 | RSAPublicKey publicKey) throws Exception { 261 | // 模长 262 | int key_len = publicKey.getModulus().bitLength() / 8; 263 | byte[] bytes = data.getBytes(); 264 | byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 265 | // 如果密文长度大于模长则要分组解密 266 | String ming = ""; 267 | byte[][] arrays = splitArray(bcd, key_len); 268 | for (byte[] arr : arrays) { 269 | ming += new String(decryptByPublicKey(arr, publicKey)); 270 | } 271 | return ming; 272 | } 273 | 274 | /** 275 | * 公钥解密 276 | * @desc 277 | * @param data 278 | * @param publicKey 279 | * @return 280 | * @throws Exception 281 | */ 282 | public static byte[] decryptByPublicKey(byte[] data, 283 | RSAPublicKey publicKey) throws Exception { 284 | Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider()); 285 | cipher.init(Cipher.DECRYPT_MODE, publicKey); 286 | return cipher.doFinal(data); 287 | } 288 | 289 | /** 290 | * ASCII码转BCD码 291 | * 292 | */ 293 | private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) { 294 | byte[] bcd = new byte[asc_len / 2]; 295 | int j = 0; 296 | for (int i = 0; i < (asc_len + 1) / 2; i++) { 297 | bcd[i] = asc_to_bcd(ascii[j++]); 298 | bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4)); 299 | } 300 | return bcd; 301 | } 302 | 303 | private static byte asc_to_bcd(byte asc) { 304 | byte bcd; 305 | 306 | if ((asc >= '0') && (asc <= '9')) 307 | bcd = (byte) (asc - '0'); 308 | else if ((asc >= 'A') && (asc <= 'F')) 309 | bcd = (byte) (asc - 'A' + 10); 310 | else if ((asc >= 'a') && (asc <= 'f')) 311 | bcd = (byte) (asc - 'a' + 10); 312 | else 313 | bcd = (byte) (asc - 48); 314 | return bcd; 315 | } 316 | 317 | /** 318 | * BCD转字符串 319 | */ 320 | private static String bcd2Str(byte[] bytes) { 321 | char temp[] = new char[bytes.length * 2], val; 322 | 323 | for (int i = 0; i < bytes.length; i++) { 324 | val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f); 325 | temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 326 | 327 | val = (char) (bytes[i] & 0x0f); 328 | temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 329 | } 330 | return new String(temp); 331 | } 332 | 333 | /** 334 | * 拆分字符串 335 | */ 336 | private static String[] splitString(String string, int len) { 337 | int x = string.length() / len; 338 | int y = string.length() % len; 339 | int z = 0; 340 | if (y != 0) { 341 | z = 1; 342 | } 343 | String[] strings = new String[x + z]; 344 | String str = ""; 345 | for (int i = 0; i < x + z; i++) { 346 | if (i == x + z - 1 && y != 0) { 347 | str = string.substring(i * len, i * len + y); 348 | } else { 349 | str = string.substring(i * len, i * len + len); 350 | } 351 | strings[i] = str; 352 | } 353 | return strings; 354 | } 355 | 356 | /** 357 | * 拆分数组 358 | */ 359 | private static byte[][] splitArray(byte[] data, int len) { 360 | int x = data.length / len; 361 | int y = data.length % len; 362 | int z = 0; 363 | if (y != 0) { 364 | z = 1; 365 | } 366 | byte[][] arrays = new byte[x + z][]; 367 | byte[] arr; 368 | for (int i = 0; i < x + z; i++) { 369 | arr = new byte[len]; 370 | if (i == x + z - 1 && y != 0) { 371 | System.arraycopy(data, i * len, arr, 0, y); 372 | } else { 373 | System.arraycopy(data, i * len, arr, 0, len); 374 | } 375 | arrays[i] = arr; 376 | } 377 | return arrays; 378 | } 379 | 380 | } 381 | --------------------------------------------------------------------------------