Android SharedPreferences加密存储方法

这一篇是整理 Android本地数据SP加密存储的方法,也是属于APP安全范畴。主要是通过AES加密方法进行加密,对Key和Value全部加密,进一步保障数据安全

方法整理如下:




import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.jlpay.connect.utils.AESUtils;
import com.jlpay.partner.application.PartnerApp;

/**
 * Created by on 2020/12/04.
 */

public class SpUtils {

    //TODO 可以考虑在内存中加一个二级缓存机制,避免频繁从SP文件中读取性能低下
    public static Context context = PartnerApp.getContext();


    /**
     * SP加密存储,Key 和 Value 均加密
     * 将所有类型数据都转为 String 后加密
     */
    private static void encryptPut(@NonNull String key, @NonNull Object value) {
        String valueStr = null;

        if (value instanceof String) {
            valueStr = (String) value;
        } else if (value instanceof Boolean) {
            valueStr = Boolean.toString((Boolean) value);
        } else if (value instanceof Integer) {
            valueStr = Integer.toString((Integer) value);
        } else if (value instanceof Float) {
            valueStr = Float.toString((Float) value);
        } else if (value instanceof Long) {
            valueStr = Long.toString((Long) value);
        }

        byte[] encryptKey = AESUtils.encrypt(AESUtils.AES_KEY.getBytes(), key.getBytes());
        String base64KeyStr = RSAUtils.byteToBase64Str(encryptKey);
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences settings = context.getSharedPreferences(context.getPackageName() + "_preferences", MODE_PRIVATE);

        if (valueStr != null && !TextUtils.isEmpty(valueStr)) {
            byte[] encryptValue = AESUtils.encrypt(AESUtils.AES_KEY.getBytes(), valueStr.getBytes());
            String base64ValueStr = RSAUtils.byteToBase64Str(encryptValue);
            settings.edit().putString(base64KeyStr, base64ValueStr).apply();

        } else {
            settings.edit().putString(base64KeyStr, "").apply();
        }
    }


    /**
     * SP解密
     */
    private static Object decryptGet(@NonNull String key, @NonNull Object defaultvalue) {
        String valueStr = null;
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences settings = context.getSharedPreferences(context.getPackageName() + "_preferences", MODE_PRIVATE);
        byte[] encryptKey = AESUtils.encrypt(AESUtils.AES_KEY.getBytes(), key.getBytes());
        String base64KeyStr = RSAUtils.byteToBase64Str(encryptKey);

        if (defaultvalue instanceof String) {
            valueStr = (String) defaultvalue;
            String settingsString = settings.getString(base64KeyStr, valueStr);
            if (settingsString != null && !TextUtils.isEmpty(settingsString) && !settingsString.equals(valueStr)) {
                byte[] bytes = RSAUtils.base64StrToByte(settingsString);
                byte[] decryptByte = AESUtils.decrypt(AESUtils.AES_KEY.getBytes(), bytes);
                String decryptStr = new String(decryptByte).trim();
                return decryptStr;
            }
            return valueStr;
        } else if (defaultvalue instanceof Boolean) {
            valueStr = Boolean.toString((Boolean) defaultvalue);
            String settingsString = settings.getString(base64KeyStr, valueStr);
            if (settingsString != null && !TextUtils.isEmpty(settingsString) && !settingsString.equals(valueStr)) {
                byte[] bytes = RSAUtils.base64StrToByte(settingsString);
                byte[] decryptByte = AESUtils.decrypt(AESUtils.AES_KEY.getBytes(), bytes);
                String decryptStr = new String(decryptByte).trim();
                return Boolean.valueOf(decryptStr);
            }
            return (boolean) defaultvalue;

        } else if (defaultvalue instanceof Integer) {
            valueStr = Integer.toString((Integer) defaultvalue);
            String settingsString = settings.getString(base64KeyStr, valueStr);
            if (settingsString != null && !TextUtils.isEmpty(settingsString) && !settingsString.equals(valueStr)) {
                byte[] bytes = RSAUtils.base64StrToByte(settingsString);
                byte[] decryptByte = AESUtils.decrypt(AESUtils.AES_KEY.getBytes(), bytes);
                String decryptStr = new String(decryptByte).trim();
                return Integer.valueOf(decryptStr);
            }
            return (int) defaultvalue;

        } else if (defaultvalue instanceof Float) {
            valueStr = Float.toString((Float) defaultvalue);
            String settingsString = settings.getString(base64KeyStr, valueStr);
            if (settingsString != null && !TextUtils.isEmpty(settingsString) && !settingsString.equals(valueStr)) {
                byte[] bytes = RSAUtils.base64StrToByte(settingsString);
                byte[] decryptByte = AESUtils.decrypt(AESUtils.AES_KEY.getBytes(), bytes);
                String decryptStr = new String(decryptByte).trim();
                return Float.valueOf(decryptStr);
            }
            return (float) defaultvalue;

        } else if (defaultvalue instanceof Long) {
            valueStr = Long.toString((Long) defaultvalue);
            String settingsString = settings.getString(base64KeyStr, valueStr);
            if (settingsString != null && !TextUtils.isEmpty(settingsString) && !settingsString.equals(valueStr)) {
                byte[] bytes = RSAUtils.base64StrToByte(settingsString);
                byte[] decryptByte = AESUtils.decrypt(AESUtils.AES_KEY.getBytes(), bytes);
                String decryptStr = new String(decryptByte).trim();
                return Long.valueOf(decryptStr);
            }
            return (long) defaultvalue;
        }
        return null;
    }


    public static String getPrefString(String key, final String defaultValue) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        return settings.getString(key, defaultValue);

        return (String) decryptGet(key, defaultValue);
    }

    public static void setPrefString(final String key, final String value) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        settings.edit().putString(key, value).apply();

        encryptPut(key, value);
    }

    public static boolean getPrefBoolean(final String key, final boolean defaultValue) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        return settings.getBoolean(key, defaultValue);

        return (boolean) decryptGet(key, defaultValue);
    }

    public static boolean hasKey(final String key) {
        return PreferenceManager.getDefaultSharedPreferences(context).contains(key);
    }

    public static void setPrefBoolean(final String key, final boolean value) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        settings.edit().putBoolean(key, value).apply();

        encryptPut(key, value);
    }

    public static void setPrefInt(final String key, final int value) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        settings.edit().putInt(key, value).apply();

        encryptPut(key, value);
    }

    public static int getPrefInt(final String key, final int defaultValue) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        return settings.getInt(key, defaultValue);

        return (int) decryptGet(key, defaultValue);
    }

    public static void setPrefFloat(final String key, final float value) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        settings.edit().putFloat(key, value).apply();

        encryptPut(key, value);
    }

    public static float getPrefFloat(final String key, final float defaultValue) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        return settings.getFloat(key, defaultValue);

        return (float) decryptGet(key, defaultValue);
    }

    public static void setSettingLong(final String key, final long value) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        settings.edit().putLong(key, value).apply();

        encryptPut(key, value);
    }

    public static long getPrefLong(final String key, final long defaultValue) {
//        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
//        return settings.getLong(key, defaultValue);

        return (long) decryptGet(key, defaultValue);
    }

    public static void clearPreference(final SharedPreferences p) {
        final SharedPreferences.Editor editor = p.edit();
        editor.clear();
        editor.apply();
    }

}

 下面是导出来的 SP文件截图:这样也无法凭Key去猜测了

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Android凭据加密存储区(Credential encrypted storage area)是一种安全存储凭据(如密码、令牌、证书等)的方式,可以保护敏感数据不被恶意应用或攻击者窃取。在使用Credential encrypted storage area时,需要创建一个Key,用于加密和解密数据。以下是一个简单的Java代码示例,演示如何使用Credential encrypted storage area: 1. 创建一个Key ``` Key key = null; KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); if (keyguardManager.isKeyguardSecure()) { // Create the keys for Credential Encrypted Storage Area KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder( "myKeyAlias", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .setUserAuthenticationRequired(true) .setUserAuthenticationValidityDurationSeconds(30); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(builder.build()); key = keyGenerator.generateKey(); } ``` 2. 存储数据 ``` String dataToStore = "my password"; byte[] encryptedData = null; try { // Get the Cipher Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key); // Encrypt the data encryptedData = cipher.doFinal(dataToStore.getBytes()); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } if (encryptedData != null) { // Store the encrypted data in the SharedPreferences SharedPreferences.Editor editor = getSharedPreferences("myPrefs", MODE_PRIVATE).edit(); editor.putString("myEncryptedData", Base64.encodeToString(encryptedData, Base64.DEFAULT)); editor.apply(); } ``` 3. 读取数据 ``` String encryptedDataString = getSharedPreferences("myPrefs", MODE_PRIVATE) .getString("myEncryptedData", null); if (encryptedDataString != null) { byte[] encryptedData = Base64.decode(encryptedDataString, Base64.DEFAULT); try { // Get the Cipher Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, key); // Decrypt the data byte[] decryptedData = cipher.doFinal(encryptedData); String data = new String(decryptedData); Log.d(TAG, "Decrypted data: " + data); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } } ``` 以上是一个简单的示例,更复杂的应用可能需要更多的代码来管理Key和加密/解密数据。同时,需要注意,Credential encrypted storage area只能在设备上启用了屏幕锁定并设置了密码、PIN码、图案等屏幕锁定方式时才能使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值