美文网首页
Android 自定义加密SharedPreferences

Android 自定义加密SharedPreferences

作者: 无敌未央様 | 来源:发表于2019-04-25 18:02 被阅读0次

    在项目开发中涉及到用户敏感信息在本地的储存问题,而SharedPreference是以明文的形式写在本地,非常不安全,要进行相应的加密。
    正好有网上有dalao已经做好了轮子,非常Thanks♪(・ω・)ノ。我在dalao的基础上增加了一个静态方法来删除存储的内容来贴合目前的项目,具体的使用方法可以参考原文,由于是继承自SharedPreference,如果懂SharedPreference怎么用的话非常好上手。
    【Android安全】自带加密光环的SharedPreference - CSDN博客 http://blog.csdn.net/voidmain_123/article/details/53338393

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.os.Build;
    import android.preference.PreferenceManager;
    import android.support.annotation.Nullable;
    import android.text.TextUtils;
    import android.util.Log;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 自动加密SharedPreference
     */
    
    public class SecuritySharedPreference implements SharedPreferences {
    
        private SharedPreferences mSharedPreferences;
        private static final String TAG = SecuritySharedPreference.class.getName();
        private Context mContext;
    
        //清空存储的内容
        public static void clear(Context context,String name) {
            SecuritySharedPreference preferences = new SecuritySharedPreference(context, name, Context.MODE_PRIVATE);
            SecuritySharedPreference.Editor editor = preferences.edit();
            editor.clear();
            editor.commit();
        }
    
        /**
         * constructor
         * @param context should be ApplicationContext not activity
         * @param name file name
         * @param mode context mode
         */
        public SecuritySharedPreference(Context context, String name, int mode){
            mContext = context;
            if (TextUtils.isEmpty(name)){
                mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
            } else {
                mSharedPreferences =  context.getSharedPreferences(name, mode);
            }
    
        }
    
        @Override
        public Map<String, String> getAll() {
            final Map<String, ?> encryptMap = mSharedPreferences.getAll();
            final Map<String, String> decryptMap = new HashMap<>();
            for (Map.Entry<String, ?> entry : encryptMap.entrySet()){
                Object cipherText = entry.getValue();
                if (cipherText != null){
                    decryptMap.put(entry.getKey(), entry.getValue().toString());
                }
            }
            return decryptMap;
        }
    
        /**
         * encrypt function
         * @return cipherText base64
         */
        private String encryptPreference(String plainText){
            return EncryptUtil.getInstance(mContext).encrypt(plainText);
        }
    
        /**
         * decrypt function
         * @return plainText
         */
        private String decryptPreference(String cipherText){
            return EncryptUtil.getInstance(mContext).decrypt(cipherText);
        }
    
        @Nullable
        @Override
        public String getString(String key, String defValue) {
            final String encryptValue = mSharedPreferences.getString(encryptPreference(key), null);
            return encryptValue == null ? defValue : decryptPreference(encryptValue);
        }
    
        @Nullable
        @Override
        public Set<String> getStringSet(String key, Set<String> defValues) {
            final Set<String> encryptSet = mSharedPreferences.getStringSet(encryptPreference(key), null);
            if (encryptSet == null){
                return defValues;
            }
            final Set<String> decryptSet = new HashSet<>();
            for (String encryptValue : encryptSet){
                decryptSet.add(decryptPreference(encryptValue));
            }
            return decryptSet;
        }
    
        @Override
        public int getInt(String key, int defValue) {
            final String encryptValue = mSharedPreferences.getString(encryptPreference(key), null);
            if (encryptValue == null) {
                return defValue;
            }
            return Integer.parseInt(decryptPreference(encryptValue));
        }
    
        @Override
        public long getLong(String key, long defValue) {
            final String encryptValue = mSharedPreferences.getString(encryptPreference(key), null);
            if (encryptValue == null) {
                return defValue;
            }
            return Long.parseLong(decryptPreference(encryptValue));
        }
    
        @Override
        public float getFloat(String key, float defValue) {
            final String encryptValue = mSharedPreferences.getString(encryptPreference(key), null);
            if (encryptValue == null) {
                return defValue;
            }
            return Float.parseFloat(decryptPreference(encryptValue));
        }
    
        @Override
        public boolean getBoolean(String key, boolean defValue) {
            final String encryptValue = mSharedPreferences.getString(encryptPreference(key), null);
            if (encryptValue == null) {
                return defValue;
            }
            return Boolean.parseBoolean(decryptPreference(encryptValue));
        }
    
        @Override
        public boolean contains(String key) {
            return mSharedPreferences.contains(encryptPreference(key));
        }
    
        @Override
        public SecurityEditor edit() {
            return new SecurityEditor();
        }
    
        @Override
        public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
            mSharedPreferences.registerOnSharedPreferenceChangeListener(listener);
        }
    
        @Override
        public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
            mSharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
        }
    
        /**
         * 处理加密过渡
         */
        public void handleTransition(){
            Map<String, ?> oldMap = mSharedPreferences.getAll();
            Map<String, String> newMap = new HashMap<>();
            for (Map.Entry<String, ?> entry : oldMap.entrySet()){
                Log.i(TAG, "key:"+entry.getKey()+", value:"+ entry.getValue());
                newMap.put(encryptPreference(entry.getKey()), encryptPreference(entry.getValue().toString()));
            }
            Editor editor = mSharedPreferences.edit();
            editor.clear().commit();
            for (Map.Entry<String, String> entry : newMap.entrySet()){
                editor.putString(entry.getKey(), entry.getValue());
            }
            editor.commit();
        }
    
        /**
         * 自动加密Editor
         */
        public final class SecurityEditor implements Editor {
    
            private Editor mEditor;
    
            /**
             * constructor
             */
            private SecurityEditor(){
                mEditor = mSharedPreferences.edit();
            }
    
            @Override
            public Editor putString(String key, String value) {
                mEditor.putString(encryptPreference(key), encryptPreference(value));
                return this;
            }
    
            @Override
            public Editor putStringSet(String key, Set<String> values) {
                final Set<String> encryptSet = new HashSet<>();
                for (String value : values){
                    encryptSet.add(encryptPreference(value));
                }
                mEditor.putStringSet(encryptPreference(key), encryptSet);
                return this;
            }
    
            @Override
            public Editor putInt(String key, int value) {
                mEditor.putString(encryptPreference(key), encryptPreference(Integer.toString(value)));
                return this;
            }
    
            @Override
            public Editor putLong(String key, long value) {
                mEditor.putString(encryptPreference(key), encryptPreference(Long.toString(value)));
                return this;
            }
    
            @Override
            public Editor putFloat(String key, float value) {
                mEditor.putString(encryptPreference(key), encryptPreference(Float.toString(value)));
                return this;
            }
    
            @Override
            public Editor putBoolean(String key, boolean value) {
                mEditor.putString(encryptPreference(key), encryptPreference(Boolean.toString(value)));
                return this;
            }
    
            @Override
            public Editor remove(String key) {
                mEditor.remove(encryptPreference(key));
                return this;
            }
    
            /**
             * Mark in the editor to remove all values from the preferences.
             * @return this
             */
            @Override
            public Editor clear() {
                mEditor.clear();
                return this;
            }
    
            /**
             * 提交数据到本地
             * @return Boolean 判断是否提交成功
             */
            @Override
            public boolean commit() {
    
                return mEditor.commit();
            }
    
            /**
             * Unlike commit(), which writes its preferences out to persistent storage synchronously,
             * apply() commits its changes to the in-memory SharedPreferences immediately but starts
             * an asynchronous commit to disk and you won't be notified of any failures.
             */
            @Override
            @TargetApi(Build.VERSION_CODES.GINGERBREAD)
            public void apply() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
                    mEditor.apply();
                } else {
                    commit();
                }
            }
        }
    }
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.os.Build;
    import android.provider.Settings;
    import android.text.TextUtils;
    import android.util.Base64;
    import android.util.Log;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * AES加密解密工具
     */
    public class EncryptUtil {
    
        private String key;
        private static EncryptUtil instance;
        private static final String TAG = EncryptUtil.class.getSimpleName();
    
    
        private EncryptUtil(Context context){
            String serialNo = getDeviceSerialNumber(context);
            //加密随机字符串生成AES key
            key = SHA(serialNo + "#$ERDTS$D%F^Gojikbh").substring(0, 16);
            Log.e(TAG, key);
        }
    
        /**
         * 单例模式
         * @param context context
         * @return
         */
        public static EncryptUtil getInstance(Context context){
            if (instance == null){
                synchronized (EncryptUtil.class){
                    if (instance == null){
                        instance = new EncryptUtil(context);
                    }
                }
            }
    
            return instance;
        }
    
        /**
         * Gets the hardware serial number of this device.
         *
         * @return serial number or Settings.Secure.ANDROID_ID if not available.
         */
        @SuppressLint("HardwareIds")
        private String getDeviceSerialNumber(Context context) {
            // We're using the Reflection API because Build.SERIAL is only available
            // since API Level 9 (Gingerbread, Android 2.3).
            try {
                String deviceSerial = (String) Build.class.getField("SERIAL").get(null);
                if (TextUtils.isEmpty(deviceSerial)) {
                    return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
                } else {
                    return deviceSerial;
                }
            } catch (Exception ignored) {
                // Fall back  to Android_ID
                return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            }
        }
    
    
        /**
         * SHA加密
         * @param strText 明文
         * @return
         */
        private String SHA(final String strText){
            // 返回值
            String strResult = null;
            // 是否是有效字符串
            if (strText != null && strText.length() > 0){
                try{
                    // SHA 加密开始
                    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
                    // 传入要加密的字符串
                    messageDigest.update(strText.getBytes());
                    byte byteBuffer[] = messageDigest.digest();
                    StringBuffer strHexString = new StringBuffer();
                    for (int i = 0; i < byteBuffer.length; i++){
                        String hex = Integer.toHexString(0xff & byteBuffer[i]);
                        if (hex.length() == 1){
                            strHexString.append('0');
                        }
                        strHexString.append(hex);
                    }
                    strResult = strHexString.toString();
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
    
            return strResult;
        }
    
    
        /**
         * AES128加密
         * @param plainText 明文
         * @return
         */
        public String encrypt(String plainText) {
            try {
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
                cipher.init(Cipher.ENCRYPT_MODE, keyspec);
                byte[] encrypted = cipher.doFinal(plainText.getBytes());
                return Base64.encodeToString(encrypted, Base64.NO_WRAP);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * AES128解密
         * @param cipherText 密文
         * @return
         */
        public String decrypt(String cipherText) {
            try {
                byte[] encrypted1 = Base64.decode(cipherText, Base64.NO_WRAP);
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
                cipher.init(Cipher.DECRYPT_MODE, keyspec);
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original);
                return originalString;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Android 自定义加密SharedPreferences

          本文链接:https://www.haomeiwen.com/subject/jjzzgqtx.html