編輯:關於Android編程
談到 Android 安全性話題,Android Developers 官方網站給出了許多很好的建議和講解,涵蓋了存儲數據、權限、網絡、處理憑據、輸入驗證、處理用戶數據、加密等方方面面
密鑰的保護以及網絡傳輸安全 應該是移動應用安全最關鍵的內容。Android 提供大量用來保護數據的加密算法,例如 Cipher 類中提供了 AES 和 RSA 算法,再例如安全隨機數生成器 SecureRandom 給 KeyGenerator 提供了更加可靠的初始化參數,避免離線攻擊等等。
而如果需要存儲密鑰以供重復使用,Android 提供了 KeyStore 等可以長期存儲和檢索加密密鑰的機制,Android KeyStore 系統特別適合於存儲加密密鑰。”AndroidKeyStore” 是 KeyStore 的一個子集,存進 AndroidKeyStore 的 key 將受到簽名保護,並且這些 key 是存在系統裡的,而不是在 App 的 data 目錄下,依托於硬件的 KeyChain 存儲,可以做到 private key 一旦存入就無法取出,總之,每個 App 自己創建的 key,別的應用是訪問不到的。
KeyStore 提供了兩個能力:
有了這兩個能力,我們的密鑰保護就變得很容易了,你只需要:
在應用安裝後第一次運行時,生成一個隨機密鑰,並存入 KeyStore
當你想存儲一個數據,便從 KeyStore 中取出之前生成的隨機密鑰,對你的數據進行加密,加密完成後,已完成加密的數據可以隨意存儲在任意地方,比如 SharePreferences,此時即使它被他人讀取到,也無法解密出你的原數據,因為他人取不到你的密鑰
當你需要拿到你的原數據,只需要從 SharePreferences 中讀取你加密後的數據,並從 KeyStore 取出加密密鑰,使用加密密鑰對 “加密後的數據” 進行解密即可
其中加密算法可以使用 Cipher AES 來保證安全性,不要使用自己創造的加密算法。
這就是使用 KeyStore 的一整套流程,另外 KeyStore 還可以用來做數據簽名和簽名驗證,就像一個黑匣子一樣,具體可以自行搜索了解。
KeyStore 適於存儲運行時生產獲取到的數據,比如運行時,用戶輸入的密碼,或者服務端傳下來的 token,但無法用於存儲我們需要預設在 App 內的 API key / secret,對於這類需要預設的固定密鑰,我將介紹一種十分安全、難破解的保護方式。
加密:
public String encryptString(String needEncryptWord, String alias) { if(!"".equals(alias)&&!"".equals(needEncryptWord)){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { initKeyStore(alias); } String encryptStr=""; byte [] vals=null; try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); // RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey(); if(needEncryptWord.isEmpty()) { // Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show(); return encryptStr; } // Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // inCipher.init(Cipher.ENCRYPT_MODE, publicKey); inCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); cipherOutputStream.write(needEncryptWord.getBytes("UTF-8")); cipherOutputStream.close(); vals = outputStream.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return Base64.encodeToString(vals, Base64.DEFAULT); } return ""; }
解密:
public String decryptString(String needDecryptWord, String alias) { if(!"".equals(alias)&&!"".equals(needDecryptWord)){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { initKeyStore(alias); } String decryptStr=""; try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); // RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey(); // Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // output.init(Cipher.DECRYPT_MODE, privateKey); output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey()); CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(needDecryptWord, Base64.DEFAULT)), output); ArrayList<Byte> values = new ArrayList<>(); int nextByte; while ((nextByte = cipherInputStream.read()) != -1) { values.add((byte)nextByte); } byte[] bytes = new byte[values.size()]; for(int i = 0; i < bytes.length; i++) { bytes[i] = values.get(i).byteValue(); } decryptStr = new String(bytes, 0, bytes.length, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return decryptStr; } return ""; }
源碼下載地址,我已經將加密解密封裝進了工具類,並對Android 7.0的兼容也處理了
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
Android N 通知欄和快捷通知欄帶來的改變Android N 引入了一些新的API,允許應用發布具有高度可見性和交互性的通知。Android N 擴展了現有 Rem
我們點開案例可以看到眾多我們熟知的軟件都是使用的這個公司所提供的SDK然後我們點擊開發者中心中的開發工具與sdk下載我們所需要的sdk之後再點擊我的應用中的創建應用之後他
紅米pro和紅米note3哪個好?下面小編帶來了兩部手機的對比評測,一起來看看吧!紅米pro和紅米note3對比評測: 紅米pro介紹: 紅米pro采用
在平時開發中柱狀形狀偶爾會有項目需求,由於又一次開發需要,去找開源的組件都不好用,要不調用很不方便,要不它們類庫太笨重,下面介紹一個輕巧方便控件,原理就是用View 重新