使用AES加密进行Android的SharedPreferences存储

1.概述

SharedPreferences是Android提供用来存储一些简单配置信息的机制,其以KEY-VALUE对的方式进行存储,以便我们可以方便进行读取和存储。主要可以用来存储应用程序的欢迎语、常量参数或登录账号密码等。

2.实例

(1)创建项目SharedPreferencesDemo项目

(2)编辑主界面的布局文件main.xml如下:

[xhtml] view
plain
copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <TextView
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="SharedPreferences,是Android提供用来存储一些简单的配置信息的一种机制。"
  11. />
  12. <EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/edtAccount" android:text=""></EditText>
  13. <EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/edtPassword" android:text=""></EditText>
  14. <Button android:text="清空" android:id="@+id/btnClear" android:layout_width="fill_parent" android:layout_height="wrap_content">    </Button>
  15. <Button android:text="退出" android:id="@+id/btnExit" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
  16. </LinearLayout>

(3)创建AES加解密工具类AESEncryptor.java

其中主要提供加密encrypt、解密decrypt两个方法。(AES加解密算法具体大家可以到网上搜索相关资料)

以下为该类文件的源码:

[java] view
plain
copy

  1. package ni.demo.sharedpreferences;
  2. import java.security.SecureRandom;
  3. import javax.crypto.Cipher;
  4. import javax.crypto.KeyGenerator;
  5. import javax.crypto.SecretKey;
  6. import javax.crypto.spec.SecretKeySpec;
  7. /**
  8. * AES加密器
  9. * @author Eric_Ni
  10. *
  11. */
  12. public class AESEncryptor {
  13. /**
  14. * AES加密
  15. */
  16. public static String encrypt(String seed, String cleartext) throws Exception {
  17. byte[] rawKey = getRawKey(seed.getBytes());
  18. byte[] result = encrypt(rawKey, cleartext.getBytes());
  19. return toHex(result);
  20. }
  21. /**
  22. * AES解密
  23. */
  24. public static String decrypt(String seed, String encrypted) throws Exception {
  25. byte[] rawKey = getRawKey(seed.getBytes());
  26. byte[] enc = toByte(encrypted);
  27. byte[] result = decrypt(rawKey, enc);
  28. return new String(result);
  29. }
  30. private static byte[] getRawKey(byte[] seed) throws Exception {
  31. KeyGenerator kgen = KeyGenerator.getInstance("AES");
  32. SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
  33. sr.setSeed(seed);
  34. kgen.init(128, sr); // 192 and 256 bits may not be available
  35. SecretKey skey = kgen.generateKey();
  36. byte[] raw = skey.getEncoded();
  37. return raw;
  38. }
  39. private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
  40. SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
  41. Cipher cipher = Cipher.getInstance("AES");
  42. cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
  43. byte[] encrypted = cipher.doFinal(clear);
  44. return encrypted;
  45. }
  46. private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
  47. SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
  48. Cipher cipher = Cipher.getInstance("AES");
  49. cipher.init(Cipher.DECRYPT_MODE, skeySpec);
  50. byte[] decrypted = cipher.doFinal(encrypted);
  51. return decrypted;
  52. }
  53. public static String toHex(String txt) {
  54. return toHex(txt.getBytes());
  55. }
  56. public static String fromHex(String hex) {
  57. return new String(toByte(hex));
  58. }
  59. public static byte[] toByte(String hexString) {
  60. int len = hexString.length()/2;
  61. byte[] result = new byte[len];
  62. for (int i = 0; i < len; i++)
  63. result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
  64. return result;
  65. }
  66. public static String toHex(byte[] buf) {
  67. if (buf == null)
  68. return "";
  69. StringBuffer result = new StringBuffer(2*buf.length);
  70. for (int i = 0; i < buf.length; i++) {
  71. appendHex(result, buf[i]);
  72. }
  73. return result.toString();
  74. }
  75. private final static String HEX = "0123456789ABCDEF";
  76. private static void appendHex(StringBuffer sb, byte b) {
  77. sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
  78. }
  79. }

(4)编辑SharedPreferencesDemo.java

源码如下:

[java] view
plain
copy

  1. package ni.demo.sharedpreferences;
  2. import android.app.Activity;
  3. import android.content.SharedPreferences;
  4. import android.content.SharedPreferences.Editor;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.Button;
  9. import android.widget.EditText;
  10. import android.widget.Toast;
  11. public class SharedPreferencesDemo extends Activity {
  12. public static final String MY_PREFERENCES = "MY_PREFERENCES";    //Preferences文件的名称
  13. public static final String MY_ACCOUNT = "MY_ACCOUNT";            //
  14. public static final String MY_PASSWORD = "MY_PASSWORD";
  15. private EditText edtAccount;
  16. private EditText edtPassword;
  17. private Button btnClear;
  18. private Button btnExit;
  19. @Override
  20. public void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.main);
  23. edtAccount = (EditText)findViewById(R.id.edtAccount);
  24. edtPassword = (EditText)findViewById(R.id.edtPassword);
  25. //获取名字为“MY_PREFERENCES”的参数文件对象,并获得MYACCOUNT、MY_PASSWORD元素的值。
  26. SharedPreferences sp = this.getSharedPreferences(MY_PREFERENCES, 0);
  27. String account = sp.getString(MY_ACCOUNT, "");
  28. String password = sp.getString(MY_PASSWORD, "");
  29. //对密码进行AES解密
  30. try{
  31. password = AESEncryptor.decrypt("41227677", password);
  32. }catch(Exception ex){
  33. Toast.makeText(this, "获取密码时产生解密错误!", Toast.LENGTH_SHORT);
  34. password = "";
  35. }
  36. //将账号和密码显示在EditText控件上。
  37. edtAccount.setText(account);
  38. edtPassword.setText(password);
  39. //获取"清空"按钮的对象,并为其绑定监听器,如被点击则清空账号和密码控件的值。
  40. btnClear = (Button)findViewById(R.id.btnClear);
  41. btnClear.setOnClickListener(new OnClickListener(){
  42. @Override
  43. public void onClick(View arg0) {
  44. edtAccount.setText("");
  45. edtPassword.setText("");
  46. }
  47. });
  48. //获取“退出”按钮的对象,并为其绑定监听,如被点击则退出程序。
  49. btnExit = (Button)findViewById(R.id.btnExit);
  50. btnExit.setOnClickListener(new OnClickListener(){
  51. @Override
  52. public void onClick(View arg0) {
  53. SharedPreferencesDemo.this.finish();
  54. }
  55. });
  56. }
  57. @Override
  58. protected void onStop() {
  59. super.onStop();
  60. //获得账号、密码控件的值,并使用AES加密算法给密码加密。
  61. String account = edtAccount.getText().toString();
  62. String password = edtPassword.getText().toString();
  63. try{
  64. password = AESEncryptor.encrypt("41227677", password);
  65. }catch(Exception ex){
  66. Toast.makeText(this, "给密码加密时产生错误!", Toast.LENGTH_SHORT);
  67. password = "";
  68. }
  69. //获取名字为“MY_PREFERENCES”的参数文件对象。
  70. SharedPreferences sp = this.getSharedPreferences(MY_PREFERENCES, 0);
  71. //使用Editor接口修改SharedPreferences中的值并提交。
  72. Editor editor = sp.edit();
  73. editor.putString(MY_ACCOUNT, account);
  74. editor.putString(MY_PASSWORD,password);
  75. editor.commit();
  76. }
  77. }

(5)效果测试

首先,在AVD我们可以看到如下界面,在两个控件上我们分别输入abc和123456。

接着,我们打开DDMS的File Explore可以看到在data->data->ni->shared_prefs下面产生了一个名字叫做MY_PREFERENCES.xml的文件,该文件就是用来存储我们刚才设置的账号和密码。

将其导出,并打开,可以看到如下内容:

<?xml version=‘1.0‘ encoding=‘utf-8‘ standalone=‘yes‘ ?>

<map>

<string name="MY_ACCOUNT">abc</string>

<string name="MY_PASSWORD">04B75FAD36E907BE50CE3222B0052B79</string>

</map>

这说明我们可以成功将账号和加密后的密码保存下来了。

最后,我们点击“退出”按钮将应用程序结束掉,再重新打开。我们又再次看到我们退出前的界面,账号密码已经被重新读取出来。

文章的最后,我们进入Android API手册,看看关于SharedPreferences的介绍:

Interface for accessing and modifying preference data returned by getSharedPreferences(String, int). For any particular set of preferences, there is a single instance of this class that all clients share. Modifications to the preferences must go through
an SharedPreferences.Editor object to ensure the preference values remain in a consistent state and control when they are committed to storage.

SharedPreferences是一个用来访问和修改选项数据的接口,通过getSharedPreferences(Stirng,int)来获得该接口。对于任何特别的选项集,只能有一个实例供所有客户端共享。针对选项参数的修改必须通过一个SharedPreferences.Editor对象来进行,以保证所有的选项值保持在一个始终如一的状态,并且通过该对象提交存储。

可见,SharedPreferences操作选项文件时是线程安全的。

在DES解密时候出现pad block corrupted错误

我这里遇见了两种情况的bug,分别用如下两种方法解决

1:              //KeyGenerator kgen = KeyGenerator.getInstance("AES"); //android4.1以后会有bug,替换下边一句

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");

2:                //Cipher cipher = Cipher.getInstance("AES"); //4.3以上有bug,用下边一句ok

Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding");

时间: 2024-10-24 19:47:38

使用AES加密进行Android的SharedPreferences存储的相关文章

Android之SharedPreferences(存储本地数据)

写入数据: // 更新写入本地缓存(用于下次无法定位时使用) // 1.实例化SharedPreferences对象(第一步) SharedPreferences mySharedPreferences = getSharedPreferences("cityinfo", MODE_PRIVATE); // 2. 实例化SharedPreferences.Editor对象(第二步) SharedPreferences.Editor editor = mySharedPreference

Android 之SharedPreferences存储

封装好的一个工具类.直接上代码: /** * @author Jenly * @date 2014-8-8 */ public class SharedPreferencesUtils { public static final String PREF_NAME = "org.king.pref_name_jenly"; public static SharedPreferences getSharedPreferences(Context context){ return getSh

Android SharedPreferences存储

一 概念 SharedPreferences存储方式是Android中存储轻量级数据的一种方式.SharedPreferences存储主要用来存储一些简单的配置信息,内部以Map方式进行存储,因此需要使用键值对提交和保存数据,保存的数据以xml格式存放在本地的/data/data/<package name>/shares_prefs文件夹下. 二 特点 1,        使用简单,便于存储轻量级的数据: 2,        只支持Java基本数据类型,不支持自定义数据类型: 3,     

【Mark】Android应用开发SharedPreferences存储数据的使用方法

Android应用开发SharedPreferences存储数据的使用方法 SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)SharedPreferences常用来存储一些轻量级的数据. 1.使用SharedPreferences保存数据方法如下: //实例化SharedPreferences对象(第一步) SharedPreferences mySharedPreferences=

处女男学Android(十三)---Android 轻量级数据存储之SharedPreferences

一.前言 转载请标明出处:http://blog.csdn.net/wlwlwlwl015/article/details/42437007 初学Android的时候在Activity之间传值我都是用Intent+Bundle这种模式去实现的,刚开始觉得没什么,后来渐渐发现了弊端,就是说只能逐层传递,当我的好几个Activity都需要从一个Activity中取数据的时候,这样就显得相当局限了,传来传去的即麻烦,又不合理,后来就想在Android中有没有web开发中类似于Session的东西,只要

Android 使用SharedPreferences进行数据存储和读取数据

很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存,如果是window软件通常我们会采用ini文件进行保存,如果是j2se应用,我们会采用properties属性文件或者xml进行保存.如果是Android应用,我们最适合采用什么方式保存软件配置参数呢?Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数.使用SharedPreferen

Android AES加密工具类实现(基础回顾)

1 package com.powercreator.cms.util; 2 3 import java.security.SecureRandom; 4 import javax.crypto.Cipher; 5 import javax.crypto.KeyGenerator; 6 import javax.crypto.SecretKey; 7 import javax.crypto.spec.IvParameterSpec; 8 import javax.crypto.spec.Secr

Android数据存储之SharedPreferences存储

安卓系统为应用提供了系统级的配置存储方案,它就是靠SharedPreferences接口来实现的,该接口存储的所有信息都是以名值对的形式保存,但其保存的数据类型也仅限于基本数据类型,如字符串.整形.布尔型等.这些配置最后会保存在一个XML文件中,每次打开应用时,这些保存的信息就会被加载进来,我们也可以在“管理应用程序”中将这些缓存数据清除. SharedPreferences接口的常用方法如下: SharedPreferences接口类方法 No 方法 类型 描述 1 public abstra

Android的移动存储之SharedPreferences

在Android系统中提供了多种存储技术.通过这些存储技术可以将数据存储在各种存储介质上.比如sharedpreferences可以将数据保存着应用软件的私有存储区,这些存储区的数据只能被写入这些数据的软件读取.当然Android还支持文件存储.SQLite数据库和Content Provider.在这里我们将对sharedpreferences存储方式进行介绍. SharedPreferences是一种轻量级的数据存储方式,学过Web开发的同学,可以想象它是一个小小的Cookie.它可以用键值