1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.math.BigInteger; 4 import java.security.KeyFactory; 5 import java.security.KeyPair; 6 import java.security.KeyPairGenerator; 7 import java.security.NoSuchAlgorithmException; 8 import java.security.NoSuchProviderException; 9 import java.security.Security; 10 import java.security.interfaces.RSAPrivateKey; 11 import java.security.interfaces.RSAPublicKey; 12 import java.security.spec.PKCS8EncodedKeySpec; 13 import java.security.spec.RSAPrivateKeySpec; 14 import java.security.spec.RSAPublicKeySpec; 15 import java.security.spec.X509EncodedKeySpec; 16 import java.util.HashMap; 17 import java.util.Map; 18 19 import javax.crypto.Cipher; 20 21 import org.apache.commons.codec.binary.Base64; 22 import org.apache.commons.lang.StringUtils; 23 import org.bouncycastle.jce.provider.BouncyCastleProvider; 24
27 28 /** 29 * 非对称加密工具 30 * 31 * @author lKF71480 32 */ 33 public class RSAUtils { 36 37 /** 38 * PublicKey4UP:用户中心公钥匙 39 */ 40 public static Map<String, Object> keyMap = new HashMap<String, Object>(); 41 42 static { 43 try { 44 Security.addProvider(new BouncyCastleProvider()); 45 } catch (Exception e) { 46 e.printStackTrace(); 47 } 48 } 49 50 /** 51 * 生成公钥和私钥 52 * 53 * @throws NoSuchAlgorithmException 54 * @throws NoSuchProviderException 55 * 56 */ 57 public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException, NoSuchProviderException { 58 HashMap<String, Object> map = new HashMap<String, Object>(); 59 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", "BC"); 60 keyPairGen.initialize(1024); 61 KeyPair keyPair = keyPairGen.generateKeyPair(); 62 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 63 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 64 65 map.put("public", publicKey); 66 map.put("private", privateKey); 67 return map; 68 } 69 70 /** 71 * 使用模和指数生成RSA公钥 72 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA 73 * /None/NoPadding】 74 * 75 * @param modulus 76 * 模 77 * @param exponent 78 * 指数 79 * @return 80 */ 81 public static RSAPublicKey getPublicKey(String modulus, String exponent) { 82 try { 83 BigInteger b1 = new BigInteger(modulus); 84 BigInteger b2 = new BigInteger(exponent); 85 KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); 86 RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2); 87 return (RSAPublicKey) keyFactory.generatePublic(keySpec); 88 } catch (Exception e) { 89 e.printStackTrace(); 90 return null; 91 } 92 } 93 94 public static RSAPublicKey getPublicKey(X509EncodedKeySpec publicKey) { 95 try { 96 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC"); 97 return (RSAPublicKey) keyfactoryNew.generatePublic(publicKey); 98 } catch (Exception e) { 99 e.printStackTrace(); 100 return null; 101 } 102 } 103 104 /** 105 * 使用模和指数生成RSA私钥 106 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA 107 * /None/NoPadding】 108 * @param modulus 模 109 * @param exponent 指数 110 * @return 111 */ 112 public static RSAPrivateKey getPrivateKey(String modulus, String exponent) { 113 try { 114 BigInteger b1 = new BigInteger(modulus); 115 BigInteger b2 = new BigInteger(exponent); 116 KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); 117 RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2); 118 return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); 119 } catch (Exception e) { 120 e.printStackTrace(); 121 return null; 122 } 123 } 124 125 /** 126 * 公钥加密 127 * 128 * @param data 129 * @param publicKey 130 * @return 131 * @throws Exception 132 */ 133 public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception { 134 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); 135 cipher.init(Cipher.ENCRYPT_MODE, publicKey); 136 // 模长 137 int key_len = publicKey.getModulus().bitLength() / 8; 138 // 加密数据长度 <= 模长-11 139 String[] datas = splitString(data, key_len - 11); 140 String mi = ""; 141 // 如果明文长度大于模长-11则要分组加密 142 for (String s : datas) { 143 mi += bcd2Str(cipher.doFinal(s.getBytes())); 144 } 145 return mi; 146 } 147 148 /** 149 * 私钥解密 150 * 151 * @param data 152 * @param privateKey 153 * @return 154 * @throws Exception 155 */ 156 public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception { 157 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); 158 cipher.init(Cipher.DECRYPT_MODE, privateKey); 159 // 模长 160 int key_len = privateKey.getModulus().bitLength() / 8; 161 byte[] bytes = data.getBytes(); 162 byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 163 System.err.println(bcd.length); 164 // 如果密文长度大于模长则要分组解密 165 String ming = ""; 166 byte[][] arrays = splitArray(bcd, key_len); 167 for (byte[] arr : arrays) { 168 ming += new String(cipher.doFinal(arr)); 169 } 170 return ming; 171 } 172 173 /** 174 * 公钥解密 175 * 176 * @param data 177 * @param privateKey 178 * @return 179 * @throws Exception 180 */ 181 public static String decryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception { 182 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); 183 cipher.init(Cipher.DECRYPT_MODE, publicKey); 184 // 模长 185 int key_len = publicKey.getModulus().bitLength() / 8; 186 byte[] bytes = data.getBytes(); 187 byte[] bcd = ASCII_To_BCD(bytes, bytes.length); 188 System.err.println(bcd.length); 189 // 如果密文长度大于模长则要分组解密 190 String ming = ""; 191 byte[][] arrays = splitArray(bcd, key_len); 192 for (byte[] arr : arrays) { 193 ming += new String(cipher.doFinal(arr)); 194 } 195 return ming; 196 } 197 /** 198 * <p> 199 * 解密 200 * </P> 201 * <功能详细描述> 202 * 203 * @return 解密后的明文 204 * @see [类、类#方法、类#成员] 205 */ 206 public static String decrypt(String cryptStr) { 207 return null; 208 } 209 210 /** 211 * ASCII码转BCD码 212 * 213 */ 214 public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) { 215 byte[] bcd = new byte[asc_len / 2]; 216 int j = 0; 217 for (int i = 0; i < (asc_len + 1) / 2; i++) { 218 bcd[i] = asc_to_bcd(ascii[j++]); 219 bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4)); 220 } 221 return bcd; 222 } 223 224 public static byte asc_to_bcd(byte asc) { 225 byte bcd; 226 227 if ((asc >= '0') && (asc <= '9')) 228 bcd = (byte) (asc - '0'); 229 else if ((asc >= 'A') && (asc <= 'F')) 230 bcd = (byte) (asc - 'A' + 10); 231 else if ((asc >= 'a') && (asc <= 'f')) 232 bcd = (byte) (asc - 'a' + 10); 233 else 234 bcd = (byte) (asc - 48); 235 return bcd; 236 } 237 238 /** 239 * BCD转字符串 240 */ 241 public static String bcd2Str(byte[] bytes) { 242 char temp[] = new char[bytes.length * 2], val; 243 244 for (int i = 0; i < bytes.length; i++) { 245 val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f); 246 temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 247 248 val = (char) (bytes[i] & 0x0f); 249 temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); 250 } 251 return new String(temp); 252 } 253 254 /** 255 * 拆分字符串 256 */ 257 public static String[] splitString(String string, int len) { 258 int x = string.length() / len; 259 int y = string.length() % len; 260 int z = 0; 261 if (y != 0) { 262 z = 1; 263 } 264 String[] strings = new String[x + z]; 265 String str = ""; 266 for (int i = 0; i < x + z; i++) { 267 if (i == x + z - 1 && y != 0) { 268 str = string.substring(i * len, i * len + y); 269 } else { 270 str = string.substring(i * len, i * len + len); 271 } 272 strings[i] = str; 273 } 274 return strings; 275 } 276 277 /** 278 * 拆分数组 279 */ 280 public static byte[][] splitArray(byte[] data, int len) { 281 int x = data.length / len; 282 int y = data.length % len; 283 int z = 0; 284 if (y != 0) { 285 z = 1; 286 } 287 byte[][] arrays = new byte[x + z][]; 288 byte[] arr; 289 for (int i = 0; i < x + z; i++) { 290 arr = new byte[len]; 291 if (i == x + z - 1 && y != 0) { 292 System.arraycopy(data, i * len, arr, 0, y); 293 } else { 294 System.arraycopy(data, i * len, arr, 0, len); 295 } 296 arrays[i] = arr; 297 } 298 return arrays; 299 } 300 301 public static String getUpPrivateEncodeStr (String encodeStr) { 302 String result = ""; 303 try { 304 RSAPrivateKey priKey = null; 305 if (keyMap.get("PrivateKey4UP") == null) { 306 String rootPath = StringUtils.remove(Thread.currentThread().getContextClassLoader().getResource("").getPath(), "classes/"); 307 String localPath = rootPath + File.separator + "keystore"; 308 File privateKeyFile = new File(localPath + File.separator + "private.key"); 309 FileInputStream privateKeyInputStream = new FileInputStream(privateKeyFile); 310 byte[] privateKeyByte = new byte[(int) privateKeyFile.length()]; 311 // 将私钥文件读入内存 312 privateKeyInputStream.read(privateKeyByte); 313 privateKeyInputStream.close(); 314 // 生成私钥钥对象privateKey 315 PKCS8EncodedKeySpec priPKCS8new = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyByte)); 316 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC"); 317 priKey = (RSAPrivateKey) keyfactoryNew.generatePrivate(priPKCS8new); 318 keyMap.put("PrivateKey4UP", priKey); 319 } else { 320 priKey = (RSAPrivateKey) keyMap.get("PrivateKey4UP"); 321 } 322 // 私钥解密 323 result = RSAUtils.decryptByPrivateKey(encodeStr, priKey); 324 } catch (Exception e) { 325 e.printStackTrace(); 326 } 327 return result; 328 } 329 330 public static String getUpPublicEncodeStr(String str) { 331 // 公钥加密 332 String result = ""; 333 try { 334 RSAPublicKey pubKey = null; 335 if (keyMap.get("PublicKey4UP") == null){ 336 // 公钥文件 337 String rootPath = StringUtils.remove(Thread.currentThread().getContextClassLoader().getResource("").getPath(), "classes/"); 338 String localPath = rootPath + File.separator + "keystore"; 339 File publicKeyFile = new File(localPath + File.separator + "publicUp.key"); 340 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 341 FileInputStream publicKeyInputStream = new FileInputStream(publicKeyFile); 342 byte[] publicKeyByte = new byte[(int) publicKeyFile.length()]; 343 // 将公钥文件读入内存 344 publicKeyInputStream.read(publicKeyByte); 345 publicKeyInputStream.close(); 346 // 生成公钥对象PublicKey 347 X509EncodedKeySpec pubX509new = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyByte)); 348 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC"); 349 pubKey = (RSAPublicKey) keyfactoryNew.generatePublic(pubX509new); 350 keyMap.put("PublicKey4UP", pubKey); 351 } else { 352 pubKey = (RSAPublicKey)keyMap.get("PublicKey4UP"); 353 } 354 result = RSAUtils.encryptByPublicKey(str, pubKey); 355 } catch (Exception e) { 356 e.printStackTrace(); 357 DEBUGGER.debug(e.getMessage()); 358 } 359 return result; 360 } 361 362 /** 363 * 获取秘钥对文件 364 * @param args 365 * @throws Exception 366 */ 367 public static void makeThePairFile(String[] args) throws Exception { 368 369 /*HashMap<String, Object> map = RSAUtils.getKeys(); 370 // 生成公钥和私钥 371 RSAPublicKey publicKey = (RSAPublicKey) map.get("public"); 372 RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private"); 373 // 生成公钥文件 374 File publicKeyFile = new File("D:" + File.separator + "public.key"); 375 FileOutputStream publicKeyStream = new FileOutputStream(publicKeyFile); 376 // 获取公钥标准编码并进行base64加密 377 String publicKeyBase = new String(Base64.encodeBase64(publicKey.getEncoded())); 378 System.out.println("公钥为:" + new String(publicKey.getEncoded())); 379 System.out.println("BASE64公钥为:" + publicKeyBase); 380 publicKeyStream.write(publicKeyBase.getBytes()); 381 publicKeyStream.close(); 382 // 383 // // // 生成私钥文件 384 File privateKeyFile = new File("D:" + File.separator + "private.key"); 385 FileOutputStream privateKeyStream = new FileOutputStream(privateKeyFile); 386 // 获取私钥标准编码并进行base64加密 387 String privateKeyBase = new String(Base64.encodeBase64(privateKey.getEncoded())); 388 System.out.println("私钥为:" + new String(privateKey.getEncoded())); 389 System.out.println("BASE64私钥为:" + privateKeyBase); 390 privateKeyStream.write(privateKeyBase.getBytes()); 391 privateKeyStream.close(); 392 393 X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase.getBytes())); 394 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase.getBytes())); 395 396 KeyFactory keyfactory = KeyFactory.getInstance("RSA"); 397 RSAPublicKey newPublicKey = (RSAPublicKey) keyfactory.generatePublic(pubX509); 398 RSAPrivateKey newPrivateKey = (RSAPrivateKey) keyfactory.generatePrivate(priPKCS8); 399 System.out.println(publicKey.equals(newPublicKey)); 400 System.out.println(privateKey.equals(newPrivateKey));*/ 401 } 402 }