我同意Reto和FiXedd的观点。客观地说,在SharedPreferences中花费大量时间和精力加密密码没有多大意义,因为任何访问您的首选项文件的攻击者都很可能还可以访问应用程序的二进制文件,因此也可以对密码进行解密。

不过,话虽如此,似乎确实有一项公开倡议,即识别那些在SharedPreferences中以明文形式存储密码的移动应用程序,并对这些应用程序发出不利的光芒。看见http:/blogs.wsj.com/位数/2011/06/08/一些顶级应用程序-放置数据风险/和http://viaforensics.com/appwatchdog举几个例子。

虽然我们需要更多地关注安全问题,但我认为,在这一特定问题上的这种关注实际上并不能显著提高我们的整体安全性。然而,感知是一样的,这里有一个解决方案来加密您放置在SharedPreferences中的数据。

只需将您自己的SharedPreferences对象包装在这个对象中,您所读/写的任何数据都将自动加密和解密。例如。final SharedPreferences prefs = new ObscuredSharedPreferences(

this, this.getSharedPreferences(MY_PREFS_FILE_NAME, Context.MODE_PRIVATE) );

// eg.    prefs.edit().putString("foo","bar").commit();prefs.getString("foo", null);

下面是这个类的代码:/**

* Warning, this gives a false sense of security.  If an attacker has enough access to

* acquire your password store, then he almost certainly has enough access to acquire your

* source binary and figure out your encryption key.  However, it will prevent casual

* investigators from acquiring passwords, and thereby may prevent undesired negative

* publicity.

*/public class ObscuredSharedPreferences implements SharedPreferences {

protected static final String UTF8 = "utf-8";

private static final char[] SEKRIT = ... ; // INSERT A RANDOM PASSWORD HERE.

// Don't use anything you wouldn't want to

// get out there if someone decompiled

// your app.

protected SharedPreferences delegate;

protected Context context;

public ObscuredSharedPreferences(Context context, SharedPreferences delegate) {

this.delegate = delegate;

this.context = context;

}

public class Editor implements SharedPreferences.Editor {

protected SharedPreferences.Editor delegate;

public Editor() {

this.delegate = ObscuredSharedPreferences.this.delegate.edit();

}

@Override

public Editor putBoolean(String key, boolean value) {

delegate.putString(key, encrypt(Boolean.toString(value)));

return this;

}

@Override

public Editor putFloat(String key, float value) {

delegate.putString(key, encrypt(Float.toString(value)));

return this;

}

@Override

public Editor putInt(String key, int value) {

delegate.putString(key, encrypt(Integer.toString(value)));

return this;

}

@Override

public Editor putLong(String key, long value) {

delegate.putString(key, encrypt(Long.toString(value)));

return this;

}

@Override

public Editor putString(String key, String value) {

delegate.putString(key, encrypt(value));

return this;

}

@Override

public void apply() {

delegate.apply();

}

@Override

public Editor clear() {

delegate.clear();

return this;

}

@Override

public boolean commit() {

return delegate.commit();

}

@Override

public Editor remove(String s) {

delegate.remove(s);

return this;

}

}

public Editor edit() {

return new Editor();

}

@Override

public Map getAll() {

throw new UnsupportedOperationException(); // left as an exercise to the reader

}

@Override

public boolean getBoolean(String key, boolean defValue) {

final String v = delegate.getString(key, null);

return v!=null ? Boolean.parseBoolean(decrypt(v)) : defValue;

}

@Override

public float getFloat(String key, float defValue) {

final String v = delegate.getString(key, null);

return v!=null ? Float.parseFloat(decrypt(v)) : defValue;

}

@Override

public int getInt(String key, int defValue) {

final String v = delegate.getString(key, null);

return v!=null ? Integer.parseInt(decrypt(v)) : defValue;

}

@Override

public long getLong(String key, long defValue) {

final String v = delegate.getString(key, null);

return v!=null ? Long.parseLong(decrypt(v)) : defValue;

}

@Override

public String getString(String key, String defValue) {

final String v = delegate.getString(key, null);

return v != null ? decrypt(v) : defValue;

}

@Override

public boolean contains(String s) {

return delegate.contains(s);

}

@Override

public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {

delegate.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);

}

@Override

public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {

delegate.unregisterOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);

}

protected String encrypt( String value ) {

try {

final byte[] bytes = value!=null ? value.getBytes(UTF8) : new byte[0];

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));

Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),

Settings.Secure.ANDROID_ID).getBytes(UTF8), 20));

return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP),UTF8);

} catch( Exception e ) {

throw new RuntimeException(e);

}

}

protected String decrypt(String value){

try {

final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0];

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));

Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),

Settings.Secure.ANDROID_ID).getBytes(UTF8), 20));

return new String(pbeCipher.doFinal(bytes),UTF8);

} catch( Exception e) {

throw new RuntimeException(e);

}

}}

android设置存储,在android应用程序中存储用户设置的最合适方法是什么?相关推荐

  1. Kvaser Android驱动程序已经在许多应用程序中得到了成功的应用

    Kvaser的Android驱动程序,使您能够将Kvaser USB和Wifi等CAN总线接口连接到基于Android的平板电脑和智能手机上,同时提供Java和C/ c++ API,用于为基于Andr ...

  2. 将uni-app打包的H5放在 Android程序中在 webview 显示的两种方法

    将uni-app打包的H5放在 Android程序中在 webview 显示的两种方法 前言 Hash History 完事 前言 之前有个项目要同时做小程序和APP,本着节省时间的想法,研究了下un ...

  3. 在Delphi程序中调用控制面板设置功能

    ====================================================== 注:本文源代码点此下载 ================================= ...

  4. 如何在WordPress中为用户设置自定义头像(Gravatar替代)

    Have you ever wanted to set custom avatars for users who leave comments with no Gravatar? Or want to ...

  5. Confluence 6 选项 2 – 转移 Crowd/Jira 应用程序中的用户和用户组到 Co

    当你打算合并的外部目录服务器(Crowd 或 Jira 应用)有大量的用户到 Confluence 数据库中的时候,请使用这个选项.你需要有基本的 SQL 知识才能完成这个任务. 下面的 SQL 命令 ...

  6. react 交互_如何在React应用程序中跟踪用户交互

    react 交互 by Faouzi Oudouh 通过Faouzi Oudouh 如何在React应用程序中跟踪用户交互 (How to track user interactions in you ...

  7. 教你如何使用Solitude评估应用程序中的用户隐私问题

    本文主要介绍如何使用Solitude评估应用程序中的用户隐私问题. 关于Solitude Solitude是一款功能强大的隐私安全分析工具,可以帮助广大研究人员根据自己的需要来进行隐私问题调查.无论是 ...

  8. 怎么将c语言作业保存到word,C++程序中导出Word文档的简易方法_c语言

    如果您要在应用程序中处理Word文档,可以参考MSDN. Lori Turner. Automating Microsoft Office 97 and Office 2000,该文内容详细全面,但是 ...

  9. Qt 程序中获取 CPUID UUID 等系统信息的方法(win 平台,wmic)

    Qt 程序中获取 CPUID UUID 等系统信息的方法(win 平台,wmic) 最近的程序中要加入序列号注册的功能.这就需要获得电脑的一些基本信息,比如 UUID .或者 CPUID 一类的固定的 ...

  10. 微信小程序- css相比,wxss区别?小程序关联微信公众号如何确定用户的唯一性?微信小程序中的用户ID(openid和unionid)

    1 与css相比, wxss区别? 1) 响应式长度 rpx 2) 样式导入 3) 小程序不支持通配符* *{ width:100rpx; height:100rpx; } 2 小程序关联微信公众号如 ...

最新文章

  1. Matlab读取txt文本并且绘制曲线
  2. 程序员如何对待自己的工作
  3. python序列_科学网—Python:序列(字符串、列表、元组)和序列函数 - 刘洋洋的博文...
  4. Qt之QHeaderView排序
  5. python3 快速排序
  6. python实时获取子进程输出_Python 从subprocess运行的子进程中实时获取输出的例子...
  7. hdfs路径 linux路径,四、记录1----获取hdfs上FileSystem的方法 记录2:正则匹配路径:linux、hdfs...
  8. 服务器系统重置,云服务器系统重置
  9. 上传文件到某文件夹时,提示...路径访问被拒绝
  10. 聚能聊每周精选 第十一期
  11. Android studio中单项选择,Android studio单选按钮、复选按钮
  12. laravel框架学习(三)
  13. qt调用python(不是python调用qt,不是使用pyqt模块)
  14. 移动通信原理B-------例题解答2
  15. 阿里图标库——批量下载图标
  16. 计算机算法实验报告二——递归
  17. 索引算法原理解析(B-tree以及磁盘存储原理)
  18. VBS 请求WebAPI接口_如何设计WEB API
  19. 怎样给蔬菜图片抠图?看看这个马路中央的紫茄子
  20. 逆滤波和维纳滤波(附Matlab完整代码)

热门文章

  1. Mac 终端连接linux程服务器并相互传输文件
  2. 使用pickle模块打包停用词表,加快处理文本数据的速度
  3. kubernetes 磁盘、PV、PVC
  4. Mouse Event (Java AWT)
  5. 状压[Jxoi2012]奇怪的道路
  6. TestNG – Dependency Test
  7. ArcMAP获取要素的外包多边形
  8. 将pdf书籍变成横排的方法
  9. 如何实现上一条、下一条的功能
  10. python交互解释器_Python 交互解释器