寫這篇博客實際上是有點意外的,來源最初也算是入職當前這家公司算吧,因爲項目要求數據幾乎都進行了加密(政府項目麼!!!),當時看到這塊就想好好看看這塊的東西,苦於時間一直尋找不開,慢慢的都忘記了,突然有天在網上看到一些關於加密的博客,討論到說支付寶這樣的商業軟件加密是如何進行操做,後來瞭解了下,因爲我是作android開發的因此我想固然的就下載了一個支付寶的android版本,進階着就是火燒眉毛的改後綴,而後看看內部構造,發現支付寶的.so文件是超級多,那麼問題來了,對於支付寶這樣當量的用戶,放到android 的java層去加密確定是不合適的,這裏來源於java語言的不安全性的考慮。多的不說apk的反編譯,一旦反編譯了看到了你java加密算法,臥槽,那問題就大了去了,估計馬雲爸爸想殺人的新都有,那麼很顯然對於支付寶而言確定不能這麼幹,那麼多的.so就很能說明問題了(加密是經過jni使用C代碼實現的加密)。java
那麼到了這裏加密基本算是確認了,要是想保證你的數據的安全放到.so裏會更加的安全(android上纔有的東西哈).android
說道加密那麼就進入到本篇博客的主題,加密算法之RSA非對稱的加密算法。直譯爲私鑰加密,公鑰解密。其實也是很簡單了,私鑰只要你本身知道就行了,這樣就能保證加密的數據只能你本身才能解密。公鑰能夠公開,公鑰僅僅是用於加密的,是沒法用於去解密數據的。算法
RSA非對稱的算法,也是不可逆的,不可逆就是沒法根據公鑰獲得其算法,而後根據公鑰去獲去私鑰!!!安全
好了 ,基本的講解就這些吧,緊接着一塊兒來看下關於Java中的一些RSA的使用吧!!!dom
Java使用分爲三步走戰略!!!測試
1,生成私鑰和祕鑰編碼
2,公鑰加密
加密
3,私鑰解密spa
看到這裏是否是很so easy.code
java代碼生成私鑰和祕鑰以下代碼:
/** *生成私鑰 公鑰 */ public static void geration(){ KeyPairGenerator keyPairGenerator; try { keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(new Date().toString().getBytes()); keyPairGenerator.initialize(1024, secureRandom); KeyPair keyPair = keyPairGenerator.genKeyPair(); byte[] publicKeyBytes = keyPair.getPublic().getEncoded(); FileOutputStream fos = new FileOutputStream(PUBLIC_KEY_PATH); fos.write(publicKeyBytes); fos.close(); byte[] privateKeyBytes = keyPair.getPrivate().getEncoded(); fos = new FileOutputStream(PRIVATE_KEY_PATH); fos.write(privateKeyBytes); fos.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
獲去公鑰代碼以下:
/** * 獲取公鑰 * @param filename * @return * @throws Exception */ public static PublicKey getPublicKey(String filename) throws Exception { File f = new File(filename); FileInputStream fis = new FileInputStream(f); DataInputStream dis = new DataInputStream(fis); byte[] keyBytes = new byte[(int)f.length()]; dis.readFully(keyBytes); dis.close(); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); }
獲去私鑰的代碼以下:
/** * 獲取私鑰 * @param filename * @return * @throws Exception */ public static PrivateKey getPrivateKey(String filename)throws Exception { File f = new File(filename); FileInputStream fis = new FileInputStream(f); DataInputStream dis = new DataInputStream(fis); byte[] keyBytes = new byte[(int)f.length()]; dis.readFully(keyBytes); dis.close(); PKCS8EncodedKeySpec spec =new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); }
測試如上代碼的可用性:
public static void main(String[] args) { geration(); String input = "!!!hello world!!!"; RSAPublicKey pubKey; RSAPrivateKey privKey; byte[] cipherText; Cipher cipher; try { cipher = Cipher.getInstance("RSA"); pubKey = (RSAPublicKey) getPublicKey(PUBLIC_KEY_PATH); privKey = (RSAPrivateKey) getPrivateKey(PRIVATE_KEY_PATH); cipher.init(Cipher.ENCRYPT_MODE, pubKey); cipherText = cipher.doFinal(input.getBytes()); //加密後的東西 System.out.println("cipher: " + new String(cipherText)); //開始解密 cipher.init(Cipher.DECRYPT_MODE, privKey); byte[] plainText = cipher.doFinal(cipherText); System.out.println("publickey: " + Base64.getEncoder().encode(cipherText)); System.out.println("plain : " + new String(plainText)); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }
測試結果以下:
cipher: D?:?=羖O縜?,^輈?$偞/致?2懁B鏣靴臧??2e嗀|?,w饞i纂W俞:&圼?G6?弒橰H桞℉鬜?=)^呸b???;皒Ddm`苣+.+? ?:& ??#f-?扴8eE]?( plain : !!!hello world!!!
如上是RSA加密的java版本
固然上述最終生成的byte寫入到了一個文件中。若是你感受這樣和你不方便你也能夠直接用base64編碼成一個字符串,保留下來。
使用Base64.getEncoder().encodeToString(keyBytes)進行編譯 使用Base64.getDecoder().decode(PUBLIC_KEY)進行解碼