1. 程式人生 > >拿來就用:Android 對sharedpreferences 資料進行加密

拿來就用:Android 對sharedpreferences 資料進行加密

先來看看效果:

這裡寫圖片描述

這裡顯示的密文就是儲存在SP中的密文,下面我們再來看看sp檔案內容

這裡寫圖片描述

這樣就起到了在sp儲存時的加密功能,下面我們來看看程式碼,加密我使用的是RSA加密,並把祕鑰儲存在androidKeyStore中,這樣就保險,更加保障了我們的祕鑰安全

  • 生成RSA祕鑰工具類:AndroidKeyStoreRSAUtils
package tsou.com.encryption.AndroidKeyStoreRSA;

import android.content.Context;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import
android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.support.annotation.RequiresApi; import android.util.Log; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyFactory; import
java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.UnrecoverableEntryException; import
java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import javax.crypto.Cipher; import javax.security.auth.x500.X500Principal; import tsou.com.encryption.aescbc.Base64Decoder; import tsou.com.encryption.androidkeystoresign.SecurityConstants; public class AndroidKeyStoreRSAUtils { public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式 public static final int DEFAULT_KEY_SIZE = 2048;//祕鑰預設長度 public static final byte[] DEFAULT_SPLIT = "#HUANGXIAOGUO#".getBytes(); // 當要加密的內容超過bufferSize,則採用partSplit進行分塊加密 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 當前祕鑰支援加密的最大位元組數 /** * 自己給你的別名,方便在keystore中查詢祕鑰 */ public static final String SAMPLE_ALIAS = "xiaoGuoKey"; /** * 自己給你的別名 就是SAMPLE_ALIAS */ private static String mAlias = null; public static void setAlias(String alias) { mAlias = alias; } /** * 建立一個公共和私人金鑰,並將其儲存使用Android金鑰儲存庫中,因此,只有 * 這個應用程式將能夠訪問鍵。 * * @param context * @throws InvalidAlgorithmParameterException * @throws NoSuchProviderException * @throws NoSuchAlgorithmException */ @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public static KeyPair generateRSAKeyPair(Context context) throws InvalidAlgorithmParameterException, NoSuchProviderException, NoSuchAlgorithmException { setAlias(SAMPLE_ALIAS); //建立一個開始和結束時間,有效範圍內的金鑰對才會生成。 Calendar start = new GregorianCalendar(); Calendar end = new GregorianCalendar(); end.add(Calendar.YEAR, 1);//往後加一年 AlgorithmParameterSpec spec; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { //使用別名來檢索的key 。這是一個key 的key ! spec = new KeyPairGeneratorSpec.Builder(context) //使用別名來檢索的關鍵。這是一個關鍵的關鍵! .setAlias(mAlias) // 用於生成自簽名證書的主題 X500Principal 接受 RFC 1779/2253的專有名詞 .setSubject(new X500Principal("CN=" + mAlias)) //用於自簽名證書的序列號生成的一對。 .setSerialNumber(BigInteger.valueOf(1337)) // 簽名在有效日期範圍內 .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); } else { //Android 6.0(或者以上)使用KeyGenparameterSpec.Builder 方式來建立, // 允許你自定義允許的的關鍵屬性和限制 spec = new KeyGenParameterSpec.Builder(mAlias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setKeySize(DEFAULT_KEY_SIZE) .setUserAuthenticationRequired(false) .setCertificateSubject(new X500Principal("CN=" + mAlias)) //, KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA224, KeyProperties.DIGEST_SHA384, // KeyProperties.DIGEST_SHA512, KeyProperties.DIGEST_MD5) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA1) .setCertificateNotBefore(start.getTime()) .setCertificateNotAfter(end.getTime()) .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) .build(); } KeyPairGenerator kpGenerator = KeyPairGenerator .getInstance(SecurityConstants.TYPE_RSA, SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE); kpGenerator.initialize(spec); KeyPair kp = kpGenerator.generateKeyPair(); return kp; } /** * 用公鑰對字串進行加密 * * @param data 原文 */ public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公鑰 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(SecurityConstants.TYPE_RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 加密資料 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(data); } /** * 私鑰加密 * * @param data 待加密資料 * @param privateKey 金鑰 * @return byte[] 加密資料 */ public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { // 得到私鑰 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(SecurityConstants.TYPE_RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 資料加密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); return cipher.doFinal(data); } /** * 公鑰解密 * * @param data 待解密資料 * @param publicKey 金鑰 * @return byte[] 解密資料 */ public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公鑰 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(SecurityConstants.TYPE_RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 資料解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, keyPublic); return cipher.doFinal(data); } /** * 使用私鑰進行解密 */ public static byte[] decryptByPrivateKey(byte[] encrypted) throws Exception { KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); if (mAlias == null) { setAlias(SAMPLE_ALIAS); } //從Android載入金鑰對金鑰儲存庫中 KeyStore.Entry entry = ks.getEntry(mAlias, null); if (entry == null) { return null; } if (!(entry instanceof KeyStore.PrivateKeyEntry)) { return null; } PrivateKey keyPrivate = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); // 解密資料 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } /** * 用公鑰對字串進行分段加密 */ public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPublicKey(data, publicKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPublicKey(buf, publicKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 分段加密 * * @param data 要加密的原始資料 * @param privateKey 祕鑰 */ public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPrivateKey(data, privateKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPrivateKey(buf, privateKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 公鑰分段解密 * * @param encrypted 待解密資料 * @param publicKey 金鑰 */ public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPublicKey(encrypted, publicKey); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最後了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 這個是以split[0]開頭 if (splitLen > 1) { if (i + splitLen < dataLen) { // 沒有超出data的範圍 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 驗證到split的最後一位,都沒有break,則表明已經確認是split段 isMatchSplit = true; } } } } else { // split只有一位,則已經匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 使用私鑰分段解密 */ public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPrivateKey(encrypted); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最後了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 這個是以split[0]開頭 if (splitLen > 1) { if (i + splitLen < dataLen) { // 沒有超出data的範圍 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 驗證到split的最後一位,都沒有break,則表明已經確認是split段 isMatchSplit = true; } } } } else { // split只有一位,則已經匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 通過字串生成私鑰,轉換伺服器傳遞過來的私鑰 */ public static PrivateKey getPrivateKey(String privateKeyData) { PrivateKey privateKey = null; try { byte[] decodeKey = Base64Decoder.decodeToBytes(privateKeyData); PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);//建立x509證書封裝類 KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定RSA privateKey = keyFactory.generatePrivate(x509);//生成私鑰 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return privateKey; } /** * 通過字串生成公鑰,轉換伺服器傳遞過來的公鑰 */ public static PublicKey getPublicKey(String publicKeyData) { PublicKey publicKey = null; try { byte[] decodeKey = Base64Decoder.decodeToBytes(publicKeyData); X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); publicKey = keyFactory.generatePublic(x509); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return publicKey; } /** * 判斷是否建立過祕鑰 * * @return * @throws KeyStoreException * @throws CertificateException * @throws NoSuchAlgorithmException * @throws IOException * @throws UnrecoverableEntryException */ public static boolean isHaveKeyStore() { try { KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); if (mAlias == null) { setAlias(SAMPLE_ALIAS); } //從Android載入金鑰對金鑰儲存庫中 KeyStore.Entry entry = ks.getEntry(mAlias, null); if (entry == null) { return false; } } catch (KeyStoreException e) { e.printStackTrace(); return false; } catch (CertificateException e) { e.printStackTrace(); return false; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } catch (UnrecoverableEntryException e) { e.printStackTrace(); return false; } return true; } /** * 獲得本地AndroidKeyStore中的公鑰 * * @return */ public static PublicKey getLocalPublicKey() { try { KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); if (mAlias == null) { setAlias(SAMPLE_ALIAS); } //從Android載入金鑰對金鑰儲存庫中 KeyStore.Entry entry = ks.getEntry(mAlias, null); if (entry == null) { return null; } if (!(entry instanceof KeyStore.PrivateKeyEntry)) { return null; } PublicKey publicKey = ((KeyStore.PrivateKeyEntry) entry).getCertificate().getPublicKey(); return publicKey; } catch (KeyStoreException e) { e.printStackTrace(); return null; } catch (CertificateException e) { e.printStackTrace(); return null; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } catch (UnrecoverableEntryException e) { e.printStackTrace(); return null; } } }


package tsou.com.encryption.androidkeystoresign;


public class SecurityConstants {
    public static final String KEYSTORE_PROVIDER_ANDROID_KEYSTORE = "AndroidKeyStore";

    public static final String TYPE_RSA = "RSA";
    public static final String TYPE_DSA = "DSA";
    public static final String TYPE_BKS = "BKS";

    public static final String SIGNATURE_SHA256withRSA = "SHA256withRSA";
    public static final String SIGNATURE_SHA512withRSA = "SHA512withRSA";
}
  • 加密封裝在SPSecuredUtils祕鑰中方便拿過來直接用
package tsou.com.encryption.sp;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.interfaces.RSAPublicKey;
import java.util.Map;

import tsou.com.encryption.AndroidKeyStoreRSA.AndroidKeyStoreRSAUtils;
import tsou.com.encryption.aescbc.Base64Decoder;
import tsou.com.encryption.aescbc.Base64Encoder;

/**
 * Created by zb666 on 2017/2/9.
 */

public class SPSecuredUtils {
    /**
     * 儲存在手機裡面的檔名
     */
    public static final String FILE_NAME = "sp_secured";
    private static SharedPreferences mSharedPreferences;

    /**
     * 儲存資料的方法,我們需要拿到儲存資料的具體型別,然後根據型別呼叫不同的儲存方法
     *
     * @param context
     * @param key
     * @param object
     * @param publicKey
     */
    public static void put(Context context, String key, Object object, RSAPublicKey publicKey) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
//        byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKeyForSpilt(encryptionString.getBytes(),
//                publicKey.getEncoded());
        try {
            if (object instanceof String) {
                byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKey(((String) object).getBytes(),
                        publicKey.getEncoded());
                editor.putString(key, Base64Encoder.encode(encryptBytes));
            } else if (object instanceof Integer) {
                put(context, key, Integer.toString((Integer) object), publicKey);
            } else if (object instanceof Boolean) {
                put(context, key, Boolean.toString((Boolean) object), publicKey);
            } else if (object instanceof Float) {
                put(context, key, Float.toString((Float) object), publicKey);
            } else if (object instanceof Long) {
                put(context, key, Long.toString((Long) object), publicKey);
            } else {
                put(context, key, object.toString(), publicKey);
            }

            SharedPreferencesCompat.apply(editor);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到儲存資料的方法,我們根據預設值得到儲存的資料的具體型別,然後呼叫相對於的方法獲取值
     *
     * @param context
     * @param key
     * @param defaultObject
     * @return
     */
    public static Object get(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
//        byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKeyForSpilt(
//                Base64Decoder.decodeToBytes(decodeString));
        try {
            if (defaultObject instanceof String) {
                String string = sp.getString(key, (String) defaultObject);
                if (!string.equals((String) defaultObject)) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return new String(decryptBytes);
                }
                return (String) defaultObject;
            } else if (defaultObject instanceof Integer) {
                String string = sp.getString(key, Integer.toString((Integer) defaultObject));
                if (!string.equals(Integer.toString((Integer) defaultObject))) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return Integer.valueOf(new String(decryptBytes));
                }
                return (Integer) defaultObject;
            } else if (defaultObject instanceof Boolean) {
                String string = sp.getString(key, Boolean.toString((Boolean) defaultObject));
                if (!string.equals(Boolean.toString((Boolean) defaultObject))) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return Boolean.valueOf(new String(decryptBytes));
                }
                return (Boolean) defaultObject;
            } else if (defaultObject instanceof Float) {
                String string = sp.getString(key, Float.toString((Float) defaultObject));
                if (!string.equals(Float.toString((Float) defaultObject))) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return Float.valueOf(new String(decryptBytes));
                }
                return (Float) defaultObject;
            } else if (defaultObject instanceof Long) {
                String string = sp.getString(key, Long.toString((Long) defaultObject));
                if (!string.equals(Long.toString((Long) defaultObject))) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return Long.valueOf(new String(decryptBytes));
                }
                return (Long) defaultObject;
            }else if (defaultObject instanceof Double){
                String string = sp.getString(key, Double.toString((Double) defaultObject));
                if (!string.equals(Double.toString((Double) defaultObject))) {
                    byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                            Base64Decoder.decodeToBytes(string));
                    return Double.valueOf(new String(decryptBytes));
                }
                return (Double) defaultObject;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 將物件儲存到sharepreference
     *
     * @param key
     * @param device
     * @param <T>
     */
    public static <T> boolean saveDeviceData(Context context, String key, T device, RSAPublicKey publicKey) {
        if (mSharedPreferences == null) {
            mSharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {   //Device為自定義類
            // 建立物件輸出流,並封裝位元組流
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            // 將物件寫入位元組流
            oos.writeObject(device);
            // 將位元組流編碼成base64的字串
            String oAuth_Base64 = new String(Base64.encode
                    (baos.toByteArray(), Base64.DEFAULT));
            byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKey(oAuth_Base64.getBytes(),
                    publicKey.getEncoded());
            mSharedPreferences.edit().putString(key, Base64Encoder.encode(encryptBytes)).apply();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將物件從shareprerence中取出來
     *
     * @param key
     * @param <T>
     * @return
     */
    public static <T> T getDeviceData(Context context, String key) {
        if (mSharedPreferences == null) {
            mSharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        }
        try {
            T device = null;
            String productBase64 = mSharedPreferences.getString(key, null);
            if (productBase64 == null) {
                return null;
            }
            byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(
                    Base64Decoder.decodeToBytes(productBase64));
            // 讀取位元組
            byte[] base64 = Base64.decode(new String(decryptBytes).getBytes(), Base64.DEFAULT);
            // 封裝到位元組流
            ByteArrayInputStream bais = new ByteArrayInputStream(base64);
            // 再次封裝
            ObjectInputStream bis = new ObjectInputStream(bais);
            // 讀取物件
            device = (T) bis.readObject();
            return device;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 移除某個key值已經對應的值
     *
     * @param context
     * @param key
     */
    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 清除所有資料
     *
     * @param context
     */
    public static void clear(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 查詢某個key是否已經存在
     *
     * @param context
     * @param key
     * @return
     */
    public static boolean contains(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.contains(key);
    }

    /**
     * 返回所有的鍵值對
     *
     * @param context
     * @return
     */
    public static Map<String, ?> getAll(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.getAll();
    }

    /**
     * 建立一個解決SharedPreferencesCompat.apply方法的一個相容類
     *
     * @author zhy
     */
    private static class SharedPreferencesCompat {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查詢apply的方法
         *
         * @return
         */
        @SuppressWarnings({"unchecked", "rawtypes"})
        private static Method findApplyMethod() {
            try {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e) {
            }

            return null;
        }

        /**
         * 如果找到則使用apply執行,否則使用commit
         *
         * @param editor
         */
        public static void apply(SharedPreferences.Editor editor) {
            try {
                if (sApplyMethod != null) {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            }
            editor.commit();
        }
    }

}
  • 執行操作
package tsou.com.encryption.activity.SP;

import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.interfaces.RSAPublicKey;

import tsou.com.encryption.AndroidKeyStoreRSA.AndroidKeyStoreRSAUtils;
import tsou.com.encryption.R;
import tsou.com.encryption.aescbc.Base64Encoder;
import tsou.com.encryption.sp.SPSecuredUtils;

public class SPActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText encryptionContext;
    private Button encryption;
    private TextView tvEncryption;
    private Button decode;
    private TextView tvDecode;
    private Activity mActivity;
    private Context mContext;
    private RSAPublicKey publicKey;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aes);
        mActivity = this;
        mContext = this;
        encryptionContext = (EditText) findViewById(R.id.et_encryption_context);
        encryption = (Button) findViewById(R.id.btn_encryption);
        tvEncryption = (TextView) findViewById(R.id.tv_encryption);
        decode = (Button) findViewById(R.id.btn_decode);
        tvDecode = (TextView) findViewById(R.id.tv_decode);
        encryption.setText("存入");
        decode.setText("讀取");
        initListener();
    }

    private void initListener() {
        encryption.setOnClickListener(this);
        decode.setOnClickListener(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (AndroidKeyStoreRSAUtils.isHaveKeyStore()) {//是否有祕鑰
            publicKey = (RSAPublicKey) AndroidKeyStoreRSAUtils.getLocalPublicKey();
            if (publicKey != null) {
                Toast.makeText(mContext, "已經生成過金鑰對", Toast.LENGTH_SHORT).show();
                return;
            }
        }
        try {//在專案中放在application或啟動頁中
            KeyPair keyPair = AndroidKeyStoreRSAUtils.generateRSAKeyPair(mContext);
            // 公鑰
            publicKey = (RSAPublicKey) keyPair.getPublic();
        } catch (InvalidAlgorithmParameterExcept