Android SharedPreference MD5 哈希校验

对于某些比较重要的,只是用来判断是否匹配是否一致的数据,我们可以使用 MD5 做一次哈希,这样,至少不会是明文保存和传输,一看到字符串知道是啥数据的悲剧

我们假设 SharedPreference 需要存储一个表示当前 APP 标识的字符串 token

1522381039.imyufei
说明
1522381039 生成 token 数据时的时间戳
imyufei 客户端唯一标识

我们在不使用 MD5 之前,那么文本操作就类似于

editor.putString("token","1522381039.imyufei");
editor.commit();

当这样明文保存肯定不好啊,大家都知道 token 是啥意思,大家都知道我是 imyufei

我们想要的就是保存这样的字符串 1522381039.a675bcb1d0d9461ce75eedf616255806

editor.putString("token","1522381039.a675bcb1d0d9461ce75eedf616255806");
editor.commit();

神,谁一眼就能看出这是啥啊,对吧

a675bcb1d0d9461ce75eedf616255806 这个字符串,就是用 MD5 生成的

MD5

首先要说明的是

MD5 不是加密算法,不是加密算法,不是加密算法

它只是一个哈希校验算法,通俗的解释就是一致性匹配算法

MD5 ( Message Digest Algorithm MD5) ,中文消息摘要算法第五版,是计算机安全领域广泛 使用的一种散列函数,用以提供消息的完整性保护

简单的说,就是它可以把一段非常长的文本,压缩哈希成一个只有 128 字节的数据,可用于防止中间传递人修改数据

举个例子,A 想要通过 B 肉身那一些文件给 C,但又怕 B 中间给调包了,于是他想出了先用 MD5 算法把文件内容摘要一下,然后通过电报把这个摘要的信息发给 C,同时通过 B 把文件带给 C 。 C 收到文件后,也用 MD5 把文件摘要一下,如果和 A 发过来的摘要文本一样,就说明 B 是好人,没有调包

MD5值唯一吗 ?

不唯一,一个原始数据只对应一个 MD5 值,但是一个 MD5 值可能对应多个原始数据

MD5 能破解吗?

MD5 不可逆,就是说没有对应的算法,无法从生成的 MD5 值逆向得到原始数据

但现在很多人都有庞大的彩虹库,保存了几亿甚至几十亿的 MD5 值,可以用于反向查询得到可能的原始数据

Java 中的 MD5

Java 如何使用 MD5 的文章网上一大堆,我们这里就不解释了,直接贴出常用的 MD5 帮助类

package cn.twle.android.common;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Helper {
    public static String get(String content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(content.getBytes());
            return hexHash(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String hexHash(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    }
}

使用 MD5 对 SharedPreference 中的数据做签名

我们写一个 demo 来演示如何使用 MD5 对 SharedPreference 中的数据做签名


  1. 创建一个 空的 Android 项目 cn.twle.android.SDMD5

  2. 修改 activity_main.xml 添加两个 TextView 和一个 Button

    <?xml version="1.0" encoding="utf-8" ?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        android:orientation="vertical" >
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="请输入你的用户名" />
    
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/ms_username"
            android:text="imyufei" />
    
        <Button
                android:id="@+id/btn_sign"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="生成 Token"/>
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/ms_rs_md5"
            android:text="" />
    
    </LinearLayout>
    
  3. 新建一个包 cn.twle.android.common 并创建 MD5 帮助类 MD5Helper.java

    package cn.twle.android.common;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class MD5Helper {
        public static String get(String content) {
            try {
                MessageDigest digest = MessageDigest.getInstance("MD5");
                digest.update(content.getBytes());
                return hexHash(digest);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static String hexHash(MessageDigest digest) {
            StringBuilder builder = new StringBuilder();
            for (byte b : digest.digest()) {
                builder.append(Integer.toHexString((b >> 4) & 0xf));
                builder.append(Integer.toHexString(b & 0xf));
            }
            return builder.toString();
        }
    }
    
  4. 然后在 MainActivity.java 目录下创建一个 SharedPreferences 的帮助类 SharedHelper.java

    package cn.twle.android.sdmd5;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class SharedHelper {
    
        private Context mContext;
    
        public SharedHelper() {
        }
    
        public SharedHelper(Context mContext) {
            this.mContext = mContext;
        }
    
        //定义一个保存数据的方法
        public void save(String key, String value) {
            SharedPreferences sp = mContext.getSharedPreferences("ms_sp", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString(key,value);
            editor.commit();
        }
    
        //定义一个读取 SP 文件的方法
        public String read(String key ) {
            Map<String, String> data = new HashMap<String, String>();
            SharedPreferences sp = mContext.getSharedPreferences("ms_sp", Context.MODE_PRIVATE);
            return sp.getString(key,"");
        }
    }
    
  5. 修改 MainActivity.java 给按钮添加点击事件

    package cn.twle.android.sdmd5;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import cn.twle.android.common.MD5Helper;
    
    public class MainActivity extends AppCompatActivity {
    
        TextView ms_rs_md5;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button btn_sign = (Button) findViewById(R.id.btn_sign);
    
            final TextView ms_username = findViewById(R.id.ms_username);
            ms_rs_md5 = findViewById(R.id.ms_rs_md5);
    
            btn_sign.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String username = ms_username.getText().toString();
                    String tm_now = String.valueOf(System.currentTimeMillis());
    
                    String token = MD5Helper.get(tm_now + "." + username);
    
                    SharedHelper sh = new SharedHelper(MainActivity.this);
    
                    sh.save("token",tm_now + "." + token);
                    ms_rs_md5.setText(sh.read("token"));
    
                    Toast.makeText(MainActivity.this, "信息已写入 SharedPreference 中", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    

注意,这个时间戳时毫秒的,可以自己转成秒

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.