在上一篇文章中,咱們已經將密鑰的生成方法和流程,概括總結。而本篇主要是講如何利用密鑰進行加解密。html
首先,在上一篇文章中的咱們生成了不少密鑰,證書等等。apache
在上述生成的文件中,接收服務端加密報文:pkcs8_private_key.pem給安卓使用解密,private_key.p12 給IOS使用解密(IOS加密是public_key.der文件),rsa_public_key.pem是JAVA服務器端使用的加密密鑰(雙向通訊須要用兩套不同的密鑰)。發送加密報文:rsa_public_key.pem給安卓使用加密,public_key.der給IOS使用加密,pkcs8_private_key.pem在服務器端進行解密密鑰。服務器
其次,打開密鑰文件後,通常長這個樣子。oracle
因而爲了將其利用起來,寫了以下代碼:app
1 public static String readWantedText(String url) { 2 try { 3 FileReader fr = new FileReader(url); 4 BufferedReader br = new BufferedReader(fr); 5 StringBuffer sb = new StringBuffer(); 6 7 String temp = "";// 用於臨時保存每次讀取的內容 8 temp = br.readLine(); 9 while ((temp = br.readLine()) != null) { 10 if (temp.charAt(0) == '-') { 11 continue; 12 } 13 sb.append(temp); 14 } 15 16 return sb.toString(); 17 18 } catch (Exception e) { 19 e.printStackTrace(); 20 return null; 21 } 22 }
得到以上密鑰字符串以後,再將其轉化爲可用的密鑰,轉化私鑰代碼以下框架
1 public static PrivateKey getPrivateKey(String key) throws Exception { 2 3 byte[] keyBytes = key.getBytes(); 4 keyBytes = Base64.decodeBase64(keyBytes); 5 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); 6 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 7 PrivateKey privateKey = keyFactory.generatePrivate(keySpec); 8 return privateKey; 9 }
轉化公鑰代碼以下:函數
1 public static PublicKey getPublicKey(String key) throws Exception { 2 3 byte[] keyBytes = key.getBytes(); 4 keyBytes = Base64.decodeBase64(keyBytes); 5 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 6 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 7 PublicKey publicKey = keyFactory.generatePublic(keySpec); 8 return publicKey; 9 }
而後,獲得了密鑰以後咱們進行加解密操做,其中一個重要的點就是117 能夠參考此篇博文:http://www.metsky.com/archives/657.html,詳細瞭解。這裏關注點是,加密117字節加密 一下,解密用128解密。測試
加密函數以下:加密
1 public static final String KEY_ALGORITHM = "RSA"; 2 private static final int MAX_ENCRYPT_BLOCK = 117; 3 private static final int MAX_DECRYPT_BLOCK = 128; 4 5 public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { 6 byte[] keyBytes = Base64Utils.decode(publicKey); 7 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 8 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 9 Key publicK = keyFactory.generatePublic(x509KeySpec); 10 // 對數據加密 11 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 12 cipher.init(Cipher.ENCRYPT_MODE, publicK); 13 int inputLen = data.length; 14 ByteArrayOutputStream out = new ByteArrayOutputStream(); 15 int offSet = 0; 16 byte[] cache; 17 int i = 0; 18 // 對數據分段加密 19 while (inputLen - offSet > 0) { 20 if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 21 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 22 } else { 23 cache = cipher.doFinal(data, offSet, inputLen - offSet); 24 } 25 out.write(cache, 0, cache.length); 26 i++; 27 offSet = i * MAX_ENCRYPT_BLOCK; 28 } 29 byte[] encryptedData = out.toByteArray(); 30 out.close(); 31 return encryptedData; 32 }
解密函數以下:url
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; }
上兩段代碼中,涉及到的轉碼代碼爲:
1 public static byte[] decode(String base64) throws Exception { 2 return Base64.decode(base64.getBytes()); 3 } 4 14 public static String encode(byte[] bytes) throws Exception { 15 return new String(Base64.encode(bytes)); 16 }
由此 咱們就完成了對密鑰的使用,如今咱們經過一個簡單的測試代碼來檢驗咱們這幾篇文檔的成果。
1 public static void main(String[] args) { 2 3 4 String publicFilePath = "E:\\test_public_key.pem"; 5 String publickey = RSAForCommunication.readWantedText1(publicFilePath); 6 String word = "這是用來測試,加密效果的一句話,能夠試試 有多長。可是目前的狀況來看,是能夠長場產出噶哈哈哈哈哈哈哈哈啊哈哈哈哈哈啊哈哈哈哈啊啊啊哈哈哈"; 7 String encode =""; 8 try { 9 byte[] a = RSAForCommunication.encryptByPublicKey(word.getBytes(), publickey); 10 encode = Base64Utils.encode(a); 11 } catch (Exception e) { 12 13 } 14 15 System.out.println("-------加密以後的密文:"); 16 System.out.println(encode); 17 18 19 String filePath = "E:\\test_private_key.pem"; 20 String key = RSAForCommunication.readWantedText1(filePath); 21 byte[] a; 22 try { 23 a = Base64Utils.decode(encode); 24 byte[] b = decryptByPrivateKey(a, key); 25 String deCodeStr = new String(b, "utf-8"); 26 System.out.println("--------密文解密爲:"); 27 System.out.println(deCodeStr); 28 } catch (Exception ex) { 29 System.out.println("1"); 30 } 31 32 }
結果展現
最後,這裏的密文在傳輸過程當中會出現空格或者被轉義的狀況,請注意!這是由於安卓或者IOS使用了通訊框架或者其餘緣由致使。會使得通訊失敗
若是你有更好的加解密辦法請聯繫我。
——————————————————————————————————————————
補充
關於Base64的包 不建議使用 sun.misc.BASE64Encoder這個包,具體的緣由是因爲SUN公司賣給oracle以前,本身定義的一些類。並不在公佈的API中,之後隨時可能被刪除掉,因此不建議使用。
建議使用 ,如:org.apache.commons.codec.binary.Base64類