专栏首页Frank909Android常用加密手段之MD5加密(字符串加密和文件加密)

Android常用加密手段之MD5加密(字符串加密和文件加密)

前言

安全问题一直伴随着互联网的成长,如何有效地保护应用程序的数据是每一个开发者都应该考虑和努力的事情。这篇文章介绍Android平台上常用的加密方式之MD5加密。

MD5

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。 MD5算法具有以下特点: 1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。 2、容易计算:从原数据计算出MD5值很容易。 3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。 4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。 MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。

以上是百度百科上的简介。

简单来说,MD5算法是固定的,比如同一个数字它的加密结果是固定的,并且它理论上是不可逆的。(不过,现在已经可以被破解了,更多信息请自行上网搜索)

MD5常见用途

  • 登陆密码保护时将密码进行MD5加密再上传到数据库,可以防止被密码被劫持破解。如密码是123456,如果明文上传,被人获取后能轻易盗取账号,如果用md5加密后,它变成”49ba59abbe56e057”,这样即使被劫持,也难以将这串字符反译成123456
  • 检验文件完整性 网络传输文件时,受到网络环境的影响,有时会发生文件传输不完整的现象。这个时候常见的方法就是用md5校验码。如果两个文件的md5一样,那么文件就下载完整了,如果不一样说明下载不完成。

Android平台上MD5代码编写

加密字符串

在Android编写MD加密代码示例如下:

public static String md5(String content) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("NoSuchAlgorithmException",e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UnsupportedEncodingException", e);
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }

代码很简单,通过MessageDigest.getInstance("MD5")得到一个MessageDigest对象,这个类是Java自带的一个加密类。然后通过调用.digest(byte[])得到了加密后的字节数组。 得到加密后的字节数组后,我们通常要把它们转换成16进制式的字符串。 值得注意的是,在16进制中数字的正确表达应该是0x0f这种。一个数字如果超过了15就要进位,超过255就会溢出。比如十进制中17用16进制表示就是0x11。所以加密后的字节数组中,每个byte构成一个16进制的数,而这个16进制数需要两个char来表示。高位在前,低位在后。比如:

//byte[] result = byte[]{13,14,25,09}
//result[0]为0x0d,result[2]为0x19

所以很容易得到网上的转换十进制到十六进制的方法:

private static String convertByteArrayToHex(byte[] byteArray){
        // 首先初始化一个字符数组,用来存放每个16进制字符
        char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };

        // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
        char[] resultCharArray =new char[byteArray.length * 2];

        // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
        int index = 0;
        for (byte b : byteArray) {
            resultCharArray[index++] = hexDigits[b>>> 4 & 0xf];
            resultCharArray[index++] = hexDigits[b& 0xf];
        }

        // 字符数组组合成字符串返回
        return new String(resultCharArray);
    }

当然,本文的例子中转换16进制的效果与上面也是一样的

StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
            //避免出现0x5这样的数字,应该是0x05
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();

演示效果:

加密文件

我之前在项目开发中为了验证文件下载的完整性,想到了用md5去校验。思路还是将文件转换成byte数组,然后再进行Md5转码。可有时候,Android应用直接就崩掉了,原因是内存溢出。想想也是,如果一个文件太大了,比如512M,那么用byte数组来表示文件肯定就不合适。直接读到内存肯定崩掉。于是我想到在java中读取文件可以用流的形式,那么md5中有没有类似的流处理呢?答案是肯定的,这个类就是DigestInputStream.示例代码如下:

public static String md5ForFile(File file){
        int buffersize = 1024;
        FileInputStream fis = null;
        DigestInputStream dis = null;

        try {
            //创建MD5转换器和文件流
            MessageDigest messageDigest =MessageDigest.getInstance("MD5");
            fis = new FileInputStream(file);
            dis = new DigestInputStream(fis,messageDigest);

            byte[] buffer = new byte[buffersize];
            //DigestInputStream实际上在流处理文件时就在内部就进行了一定的处理
            while (dis.read(buffer) > 0);

            //通过DigestInputStream对象得到一个最终的MessageDigest对象。
            messageDigest = dis.getMessageDigest();

            // 通过messageDigest拿到结果,也是字节数组,包含16个元素
            byte[] array = messageDigest.digest();
            // 同样,把字节数组转换成字符串
            StringBuilder hex = new StringBuilder(array.length * 2);
            for (byte b : array) {
                if ((b & 0xFF) < 0x10){
                    hex.append("0");
                }
                hex.append(Integer.toHexString(b & 0xFF));
            }
            return hex.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

但有点需要注意的是,md5加密文件可能要耗时很久,所以在Android平台上开发最好是异步进行。我demo例子加密了一个188M大小的视频大概用了2秒。 演示效果:

引用

百度百科–MD5

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 自动驾驶Apollo源码分析系列感知篇(六):车道线Dark SCNN算法及车道线后处理代码简述

    车道线检测是 ADAS 领域和高级别自动驾驶都非常重要的一环,属于环境感知和定位中的核心项。 人可以轻易分辨道路上的车道线,但是对于机器而言,却非常的难,人脑...

    Frank909
  • 死磕YOLO系列,YOLOv2的自我修养

    YOLO 在当时是非常不错的算法,速度极快,但明显的缺陷就是精度问题特别是小尺寸目标检测问题上。

    Frank909
  • 【小算法】冒泡排序

    冒泡排序是大多学人学到的第一个排序,教科书上在众多的排序算法中选择它作为示例,我想还是因为它够简单,易于理解吧。

    Frank909
  • QDockWidget和setCentralWidget

    本篇将介绍主窗口剩下的Dock Widget Area和Center Widget。在Qt中,使用QDockWidget来创建浮动窗口。而Center Widg...

    zy010101
  • Qt创建菜单栏,工具栏,状态栏

    QMainWindow允许在其上创建菜单栏,工具栏和状态栏,我们就在QMainWindow上来创建它们。直接上代码,代码中有详细的注释。

    zy010101
  • R 语言中的矩阵计算

    作者:张丹(Conan) 来源:http://blog.fens.me/r-matrix/

    王诗翔呀
  • 推荐系统之矩阵分解家族

    本文主要围绕推荐系统中经典的矩阵分解技术展开讨论,先阐述推荐系统的必要性以及主流分类,随后介绍推荐系统的两大场景以及矩阵分解原理,最后开始介绍矩阵分解大家族,从...

    张小磊
  • 推荐系统之矩阵分解模型

    最近在整理Embedding技术在推荐系统中的应用,总结了获取各类item2vec的方法,推荐系统中的矩阵分解作为解决item2vec问题初期技术方法之一,虽已...

    流川枫
  • 26个顶尖战略咨询公司常用分析模型详解!

    几乎每个大型企业的高管都或多或少接受过咨询公司的培训或者相互合作过,咨询公司的常用的商业分析模型往往很有效率。

    物流IT圈
  • Matrix Factorization For Recommendation System

    原始的SVD又名奇异值分解,如果是用户评分矩阵,首先需要对缺失值进行简单的不全,比如用全局平均,然后用SVD进行分解

    AngelNH

扫码关注云+社区

领取腾讯云代金券