转载原文地址:http://www.cnblogs.com/linjiqin/p/6005626.html
根据原文的Base64工具包,自己做了修改:
1.导包:import it.sauronsoftware.base64.Base64; 自己没导这个包
2.工具包里报错的base64 一个是byte类型,修改成: return Base64.getDecoder().decode(base64.getBytes());
一个是String类型,修改成:return new String(Base64.getEncoder().encodeToString(bytes));
3.测试方法里面的 公钥加密 私钥解密 原文测试输出的加密文字是图片式的文字 传不了url里 所以自己改了下 可以去跟原文对比。
注意:
RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常:
1 Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes 2 at com.sun.crypto.provider.RSACipher.a(DashoA13*..) 3 at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..) 4 at javax.crypto.Cipher.doFinal(DashoA13*..)
RSA.java--RSA公钥/私钥/签名工具包
1 package com.rjs.util; 2 3 import java.io.ByteArrayOutputStream; 4 import java.security.Key; 5 import java.security.KeyFactory; 6 import java.security.KeyPair; 7 import java.security.KeyPairGenerator; 8 import java.security.PrivateKey; 9 import java.security.PublicKey; 10 import java.security.Signature; 11 import java.security.interfaces.RSAPrivateKey; 12 import java.security.interfaces.RSAPublicKey; 13 import java.security.spec.PKCS8EncodedKeySpec; 14 import java.security.spec.X509EncodedKeySpec; 15 import java.util.HashMap; 16 import java.util.Map; 17 18 import javax.crypto.Cipher; 19 20 /** 21 * <p> 22 * RSA公钥/私钥/签名工具包 23 * </p> 24 * <p> 25 * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman) 26 * </p> 27 * <p> 28 * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/> 29 * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/> 30 * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全 31 * </p> 32 * 33 * @author IceWee 34 * @date 2012-4-26 35 * @version 1.0 36 */ 37 public class RSA { 38 39 /** 40 * 加密算法RSA 41 */ 42 public static final String KEY_ALGORITHM = "RSA"; 43 44 /** 45 * 签名算法 46 */ 47 public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 48 49 /** 50 * 获取公钥的key 51 */ 52 private static final String PUBLIC_KEY = "RSAPublicKey"; 53 54 /** 55 * 获取私钥的key 56 */ 57 private static final String PRIVATE_KEY = "RSAPrivateKey"; 58 59 /** 60 * RSA最大加密明文大小 61 */ 62 private static final int MAX_ENCRYPT_BLOCK = 117; 63 64 /** 65 * RSA最大解密密文大小 66 */ 67 private static final int MAX_DECRYPT_BLOCK = 128; 68 69 /** 70 * <p> 71 * 生成密钥对(公钥和私钥) 72 * </p> 73 * 74 * @return 75 * @throws Exception 76 */ 77 public static Map<String, Object> genKeyPair() throws Exception { 78 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); 79 keyPairGen.initialize(1024); 80 KeyPair keyPair = keyPairGen.generateKeyPair(); 81 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 82 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 83 Map<String, Object> keyMap = new HashMap<String, Object>(2); 84 keyMap.put(PUBLIC_KEY, publicKey); 85 keyMap.put(PRIVATE_KEY, privateKey); 86 return keyMap; 87 } 88 89 /** 90 * <p> 91 * 用私钥对信息生成数字签名 92 * </p> 93 * 94 * @param data 已加密数据 95 * @param privateKey 私钥(BASE64编码) 96 * 97 * @return 98 * @throws Exception 99 */ 100 public static String sign(byte[] data, String privateKey) throws Exception { 101 byte[] keyBytes = Base64Utils.decode(privateKey); 102 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 103 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 104 PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); 105 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 106 signature.initSign(privateK); 107 signature.update(data); 108 return Base64Utils.encode(signature.sign()); 109 } 110 111 /** 112 * <p> 113 * 校验数字签名 114 * </p> 115 * 116 * @param data 已加密数据 117 * @param publicKey 公钥(BASE64编码) 118 * @param sign 数字签名 119 * 120 * @return 121 * @throws Exception 122 * 123 */ 124 public static boolean verify(byte[] data, String publicKey, String sign) 125 throws Exception { 126 byte[] keyBytes = Base64Utils.decode(publicKey); 127 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 128 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 129 PublicKey publicK = keyFactory.generatePublic(keySpec); 130 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 131 signature.initVerify(publicK); 132 signature.update(data); 133 return signature.verify(Base64Utils.decode(sign)); 134 } 135 136 /** 137 * <P> 138 * 私钥解密 139 * </p> 140 * 141 * @param encryptedData 已加密数据 142 * @param privateKey 私钥(BASE64编码) 143 * @return 144 * @throws Exception 145 */ 146 public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) 147 throws Exception { 148 byte[] keyBytes = Base64Utils.decode(privateKey); 149 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 150 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 151 Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 152 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 153 cipher.init(Cipher.DECRYPT_MODE, privateK); 154 int inputLen = encryptedData.length; 155 ByteArrayOutputStream out = new ByteArrayOutputStream(); 156 int offSet = 0; 157 byte[] cache; 158 int i = 0; 159 // 对数据分段解密 160 while (inputLen - offSet > 0) { 161 if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 162 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 163 } else { 164 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 165 } 166 out.write(cache, 0, cache.length); 167 i++; 168 offSet = i * MAX_DECRYPT_BLOCK; 169 } 170 byte[] decryptedData = out.toByteArray(); 171 out.close(); 172 return decryptedData; 173 } 174 175 /** 176 * <p> 177 * 公钥解密 178 * </p> 179 * 180 * @param encryptedData 已加密数据 181 * @param publicKey 公钥(BASE64编码) 182 * @return 183 * @throws Exception 184 */ 185 public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) 186 throws Exception { 187 byte[] keyBytes = Base64Utils.decode(publicKey); 188 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 189 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 190 Key publicK = keyFactory.generatePublic(x509KeySpec); 191 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 192 cipher.init(Cipher.DECRYPT_MODE, publicK); 193 int inputLen = encryptedData.length; 194 ByteArrayOutputStream out = new ByteArrayOutputStream(); 195 int offSet = 0; 196 byte[] cache; 197 int i = 0; 198 // 对数据分段解密 199 while (inputLen - offSet > 0) { 200 if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 201 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); 202 } else { 203 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); 204 } 205 out.write(cache, 0, cache.length); 206 i++; 207 offSet = i * MAX_DECRYPT_BLOCK; 208 } 209 byte[] decryptedData = out.toByteArray(); 210 out.close(); 211 return decryptedData; 212 } 213 214 /** 215 * <p> 216 * 公钥加密 217 * </p> 218 * 219 * @param data 源数据 220 * @param publicKey 公钥(BASE64编码) 221 * @return 222 * @throws Exception 223 */ 224 public static byte[] encryptByPublicKey(byte[] data, String publicKey) 225 throws Exception { 226 byte[] keyBytes = Base64Utils.decode(publicKey); 227 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 228 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 229 Key publicK = keyFactory.generatePublic(x509KeySpec); 230 // 对数据加密 231 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 232 cipher.init(Cipher.ENCRYPT_MODE, publicK); 233 int inputLen = data.length; 234 ByteArrayOutputStream out = new ByteArrayOutputStream(); 235 int offSet = 0; 236 byte[] cache; 237 int i = 0; 238 // 对数据分段加密 239 while (inputLen - offSet > 0) { 240 if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 241 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 242 } else { 243 cache = cipher.doFinal(data, offSet, inputLen - offSet); 244 } 245 out.write(cache, 0, cache.length); 246 i++; 247 offSet = i * MAX_ENCRYPT_BLOCK; 248 } 249 byte[] encryptedData = out.toByteArray(); 250 out.close(); 251 return encryptedData; 252 } 253 254 /** 255 * <p> 256 * 私钥加密 257 * </p> 258 * 259 * @param data 源数据 260 * @param privateKey 私钥(BASE64编码) 261 * @return 262 * @throws Exception 263 */ 264 public static byte[] encryptByPrivateKey(byte[] data, String privateKey) 265 throws Exception { 266 byte[] keyBytes = Base64Utils.decode(privateKey); 267 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 268 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 269 Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 270 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 271 cipher.init(Cipher.ENCRYPT_MODE, privateK); 272 int inputLen = data.length; 273 ByteArrayOutputStream out = new ByteArrayOutputStream(); 274 int offSet = 0; 275 byte[] cache; 276 int i = 0; 277 // 对数据分段加密 278 while (inputLen - offSet > 0) { 279 if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 280 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 281 } else { 282 cache = cipher.doFinal(data, offSet, inputLen - offSet); 283 } 284 out.write(cache, 0, cache.length); 285 i++; 286 offSet = i * MAX_ENCRYPT_BLOCK; 287 } 288 byte[] encryptedData = out.toByteArray(); 289 out.close(); 290 return encryptedData; 291 } 292 293 /** 294 * <p> 295 * 获取私钥 296 * </p> 297 * 298 * @param keyMap 密钥对 299 * @return 300 * @throws Exception 301 */ 302 public static String getPrivateKey(Map<String, Object> keyMap) 303 throws Exception { 304 Key key = (Key) keyMap.get(PRIVATE_KEY); 305 return Base64Utils.encode(key.getEncoded()); 306 } 307 308 /** 309 * <p> 310 * 获取公钥 311 * </p> 312 * 313 * @param keyMap 密钥对 314 * @return 315 * @throws Exception 316 */ 317 public static String getPublicKey(Map<String, Object> keyMap) 318 throws Exception { 319 Key key = (Key) keyMap.get(PUBLIC_KEY); 320 return Base64Utils.encode(key.getEncoded()); 321 } 322 323 }
Base64Utils.java--BASE64编码解码工具包
1 package com.rjs.util; 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 import java.util.Base64; 11 12 /*import it.sauronsoftware.base64.Base64;*/ 13 14 /** 15 * <p> 16 * BASE64编码解码工具包 17 * </p> 18 * <p> 19 * 依赖javabase64-1.3.1.jar 20 * </p> 21 * 22 * @author IceWee 23 * @date 2012-5-19 24 * @version 1.0 25 */ 26 public class Base64Utils { 27 28 /** 29 * 文件读取缓冲区大小 30 */ 31 private static final int CACHE_SIZE = 1024; 32 33 /** 34 * <p> 35 * BASE64字符串解码为二进制数据 36 * </p> 37 * 38 * @param base64 39 * @return 40 * @throws Exception 41 */ 42 public static byte[] decode(String base64) throws Exception { 43 return Base64.getDecoder().decode(base64.getBytes()); 44 } 45 46 /** 47 * <p> 48 * 二进制数据编码为BASE64字符串 49 * </p> 50 * 51 * @param bytes 52 * @return 53 * @throws Exception 54 */ 55 public static String encode(byte[] bytes) throws Exception { 56 return new String(Base64.getEncoder().encodeToString(bytes)); 57 } 58 59 /** 60 * <p> 61 * 将文件编码为BASE64字符串 62 * </p> 63 * <p> 64 * 大文件慎用,可能会导致内存溢出 65 * </p> 66 * 67 * @param filePath 68 * 文件绝对路径 69 * @return 70 * @throws Exception 71 */ 72 public static String encodeFile(String filePath) throws Exception { 73 byte[] bytes = fileToByte(filePath); 74 return encode(bytes); 75 } 76 77 /** 78 * <p> 79 * BASE64字符串转回文件 80 * </p> 81 * 82 * @param filePath 83 * 文件绝对路径 84 * @param base64 85 * 编码字符串 86 * @throws Exception 87 */ 88 public static void decodeToFile(String filePath, String base64) throws Exception { 89 byte[] bytes = decode(base64); 90 byteArrayToFile(bytes, filePath); 91 } 92 93 /** 94 * <p> 95 * 文件转换为二进制数组 96 * </p> 97 * 98 * @param filePath 99 * 文件路径 100 * @return 101 * @throws Exception 102 */ 103 public static byte[] fileToByte(String filePath) throws Exception { 104 byte[] data = new byte[0]; 105 File file = new File(filePath); 106 if (file.exists()) { 107 FileInputStream in = new FileInputStream(file); 108 ByteArrayOutputStream out = new ByteArrayOutputStream(2048); 109 byte[] cache = new byte[CACHE_SIZE]; 110 int nRead = 0; 111 while ((nRead = in.read(cache)) != -1) { 112 out.write(cache, 0, nRead); 113 out.flush(); 114 } 115 out.close(); 116 in.close(); 117 data = out.toByteArray(); 118 } 119 return data; 120 } 121 122 /** 123 * <p> 124 * 二进制数据写文件 125 * </p> 126 * 127 * @param bytes 128 * 二进制数据 129 * @param filePath 130 * 文件生成目录 131 */ 132 public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { 133 InputStream in = new ByteArrayInputStream(bytes); 134 File destFile = new File(filePath); 135 if (!destFile.getParentFile().exists()) { 136 destFile.getParentFile().mkdirs(); 137 } 138 destFile.createNewFile(); 139 OutputStream out = new FileOutputStream(destFile); 140 byte[] cache = new byte[CACHE_SIZE]; 141 int nRead = 0; 142 while ((nRead = in.read(cache)) != -1) { 143 out.write(cache, 0, nRead); 144 out.flush(); 145 } 146 out.close(); 147 in.close(); 148 } 149 150 }
RSATeste.java--测试类
1 package com.rjs.util; 2 3 import java.util.Map; 4 5 public class RSATest { 6 7 static String publicKey; 8 static String privateKey; 9 10 static { 11 try { 12 Map<String, Object> keyMap = RSA.genKeyPair(); 13 publicKey = RSA.getPublicKey(keyMap); 14 privateKey = RSA.getPrivateKey(keyMap); 15 System.err.println("公钥: " + publicKey); 16 System.err.println("私钥: " + privateKey); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 } 21 22 23 public static void main(String[] args) throws Exception { 24 test(); 25 testSign(); 26 testHttpSign(); 27 } 28 29 static void test() throws Exception { 30 String param = "id=1&name=张三"; 31 byte[] encodedData = RSA.encryptByPrivateKey(param.getBytes(), privateKey); 32 System.out.println("加密后:" + encodedData); 33 34 byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey); 35 System.out.println("解密后:" + new String(decodedData)); 36 37 String sign = RSA.sign(encodedData, privateKey); 38 System.err.println("签名:" + sign); 39 40 boolean status = RSA.verify(encodedData, publicKey, sign); 41 System.err.println("签名验证结果:" + status); 42 } 43 44 static void testSign() throws Exception { 45 System.err.println("私钥加密——公钥解密"); 46 String source = "这是一行测试RSA数字签名的无意义文字"; 47 System.out.println("原文字: " + source); 48 byte[] data = source.getBytes(); 49 byte[] encodedData = RSA.encryptByPrivateKey(data, privateKey); 50 System.out.println("加密后: " + new String(encodedData)); 51 byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey); 52 String target = new String(decodedData); 53 System.out.println("解密后: " + target); 54 System.err.println("私钥签名——公钥验证签名"); 55 String sign = RSA.sign(encodedData, privateKey); 56 System.err.println("签名: " + sign); 57 boolean status = RSA.verify(encodedData, publicKey, sign); 58 System.err.println("验证结果: " + status); 59 } 60
//原文的: 61 static void testHttpSign() throws Exception { 62 System.err.println("公钥加密——私钥解密"); 63 String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?"; 64 System.out.println(" 加密前文字: " + source); 65 byte[] data = source.getBytes(); 66 byte[] encodedData = RSA.encryptByPublicKey(data, publicKey); 67 System.out.println("加密后文字: " + new String(encodedData)); 68 byte[] decodedData = RSA.decryptByPrivateKey(encodedData, privateKey); 69 String target = new String(decodedData); 70 System.out.println("解密后文字: " + target); 71 } 72 //修改后:
static void testHttpSign() throws Exception {
System.err.println("公钥加密——私钥解密");
//自己加一个UUID,保证加密性
UUID uuid = UUID.randomUUID();
String id = uuid.toString().replaceAll("-", ""); //去除UUID的"-"符号
long time = System.currentTimeMillis();
String source = "25,18675647281,"+time;
System.out.println("
加密前文字:
" + source);
byte[] data = source.getBytes();
byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
String target = Base64Utils.encode(encodedData);
System.out.printf("加密后url:?id=%s&time=%s&v=%s
", id ,time,target);
byte[] decodedData = RSAUtils.decryptByPrivateKey(Base64Utils.decode(target), privateKey);
System.out.println("解密后文字:
" + new String(decodedData));
}
73 }