• MD5加密


    Android数据加密之MD5加密

    前言:

          项目中无论是密码的存储或者说判断文件是否是同一文件,都会用到MD5算法,今天来总结一下MD5加密算法。

    什么是MD5加密?

         MD5英文全称“Message-Digest Algorithm 5”,翻译过来是“消息摘要算法5”,由MD2、MD3、MD4演变过来的,是一种单向加密算法,是不可逆的一种的加密方式。

         其他几种加密方式:

    MD5加密有哪些特点?

    • 压缩性:任意长度的数据,算出的MD5值长度都是固定的。

    • 容易计算:从原数据计算出MD5值很容易。

    • 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

    • 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

    MD5应用场景:

    • 一致性验证

    • 数字签名

    • 安全访问认证

    MD5加密算法实现:

    1.)计算字符串MD5值

    复制代码
        public static String md5(String string) {
            if (TextUtils.isEmpty(string)) {
                return "";
            }
            MessageDigest md5 = null;
            try {
                md5 = MessageDigest.getInstance("MD5");
                byte[] bytes = md5.digest(string.getBytes());
                String result = "";
                for (byte b : bytes) {
                    String temp = Integer.toHexString(b & 0xff);
                    if (temp.length() == 1) {
                        temp = "0" + temp;
                    }
                    result += temp;
                }
                return result;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return "";
        }
    复制代码

    2.)计算文件的MD5值

    复制代码
     // 计算文件的 MD5 值
        public static String md5(File file) {
            if (file == null || !file.isFile() || !file.exists()) {
                return "";
            }
            FileInputStream in = null;
            String result = "";
            byte buffer[] = new byte[8192];
            int len;
            try {
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                in = new FileInputStream(file);
                while ((len = in.read(buffer)) != -1) {
                    md5.update(buffer, 0, len);
                }
                byte[] bytes = md5.digest();
    
                for (byte b : bytes) {
                    String temp = Integer.toHexString(b & 0xff);
                    if (temp.length() == 1) {
                        temp = "0" + temp;
                    }
                    result += temp;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(null!=in){
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return result;
        }
    复制代码

     或者采用nio的方式

    复制代码
       public static String md5(File file) {
            String result = "";
            FileInputStream in = null;
            try {
                in = new FileInputStream(file);
                MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                md5.update(byteBuffer);
                byte[] bytes = md5.digest();
                for (byte b : bytes) {
                    String temp = Integer.toHexString(b & 0xff);
                    if (temp.length() == 1) {
                        temp = "0" + temp;
                    }
                    result += temp;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != in) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return result;
        }
    复制代码

    MD5加密安全性探讨:

          虽然说MD5加密本身是不可逆的,但并不是不可破译的,网上有关MD5解密的网站数不胜数,破解机制采用穷举法,就是我们平时说的跑字典。所以如何才能加大MD5破解的难度呢?

    1.)对字符串多次MD5加密

    复制代码
        public static String md5(String string, int times) {
            if (TextUtils.isEmpty(string)) {
                return "";
            }
            String md5 = md5(string);
            for (int i = 0; i < times - 1; i++) {
                md5 = md5(md5);
            }
            return md5(md5);
        }
    复制代码

    2.)MD5加盐

         加盐的方式也是多种多样

    • string+key(盐值key)然后进行MD5加密

    • 用string明文的hashcode作为盐,然后进行MD5加密
    • 随机生成一串字符串作为盐,然后进行MD5加密

    复制代码
        public static String md5(String string, String slat) {
            if (TextUtils.isEmpty(string)) {
                return "";
            }
            MessageDigest md5 = null;
            try {
                md5 = MessageDigest.getInstance("MD5");
                byte[] bytes = md5.digest((string + slat).getBytes());
                String result = "";
                for (byte b : bytes) {
                    String temp = Integer.toHexString(b & 0xff);
                    if (temp.length() == 1) {
                        temp = "0" + temp;
                    }
                    result += temp;
                }
                return result;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return "";
        }
    复制代码

     

    Android中常用的几种加密

    1、数字摘要

      是指通过算法将长数据变为短数据,通常用来标识数据的唯一性,是否被修改,常用的加密算法有md5和sha1两种,如Android的App签名也是用的这两种算法。

      md5具有不可逆性,也可用来作为密码加密,并且通常情况下为了让加密过程变得不可预测,我们会进行加盐操作,如下代码:

    复制代码
    /**
    *  使用md5方式进行加密
    *  @return
            */
           public static String digest(String content){
            StringBuilder builder = new StringBuilder();
            try {
                MessageDigest msgDitest = MessageDigest.getInstance("MD5");
                msgDitest.update(content.getBytes());
                byte[] digests = msgDitest.digest();
                //将每个字节转为16进制
                for (int i=0;i<digests.length;i++){
                    builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return  builder.toString();
           }
    复制代码

      sha1也具有不可逆性,比md5长度更长,所以更安全,但是机密的效率md5要慢一些,如文件的秒传功能,以及相同的v4包冲突都是可以根据sha1值进行比对的。

    复制代码
    /**
    *  使用sha-1方式进行加密
    *  @return
            */
           public static String digest(String content){
            StringBuilder builder = new StringBuilder();
            try {
                MessageDigest msgDitest = MessageDigest.getInstance("SHA-1");
                msgDitest.update(content.getBytes());
                byte[] digests = msgDitest.digest();
                //将每个字节转为16进制
                for (int i=0;i<digests.length;i++){
                    builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return  builder.toString();
           }
    复制代码

    不过呢,由于以上两种生成数字摘要的算法都是不可逆的,对于可逆的加密算法中,按照密钥的数量和加密规则一半分为对称加密和非对称加密两类:

      对称加密:

        密钥可以自己指定,只有一把密钥,如果密钥泄漏数据就会暴漏;

        常用的对称加密算法有DES和AES两种;

        特点是加密速度快,但是缺点是安全性低,因为只要密钥暴漏,数据就可以被解密。

      非对称加密的特点:

        常见的非对称加密算法是RSA;

        他有两把密钥,且是由程序生成的,不能自己指定;

        特点是加密速度比较慢,但是安全性比较高;

        加密和解密的规则是:公钥加密只能私钥解密,私钥加密只能公钥解密;

        应用场景举例:在集成支付宝支付SDK时,需要生成私钥和公钥,公钥需要设置到支付宝网站的管理后台,在程序中调用支付接口的时候,使用我们自己的私钥进行加密,这样支付宝在收到订单信息之后就可以通过公钥进行解密,其他人即时劫持了数据,但是没有公钥,也是无法解密的。

      代码实践:使用AndroidUtils的工具类(工具类地址:https://github.com/zhaoyasong/ToolUtils)进行操作:

      DES加密和解密的代码如下:

      

    复制代码
    String data = "我是俊哥";
    String desKey = "青龙偃月刀";// 密钥,口号
    boolean isDesEncrypt = false;
    private void useDes() {
        try {
            if(isDesEncrypt){
                //解密
                text.setText(Des.decrypt(text.getText().toString(), desKey));
            }else {
                //加密
                text.setText(Des.encrypt(data, desKey));
            }
            isDesEncrypt = !isDesEncrypt;
        
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    复制代码

      RSA加密和解密的代码如下:

    复制代码
    //1.生成密钥对,设计口号
    try {
        Map<String, Object> genKeyPair = RSACrypt.genKeyPair();
        //2.获取公钥
        publicKey = RSACrypt.getPublicKey(genKeyPair);
        //3.获取私钥
        privateKey = RSACrypt.getPrivateKey(genKeyPair);
    } catch (Exception e) {
        e.printStackTrace();
    }
    private boolean isRSAEncrypt = false;
    protected void useRSA() {
        try {
            if(isRSAEncrypt){
                //公钥解密
                String str = text.getText().toString();
                byte[] bs = RSACrypt.decryptByPublicKey(RSACrypt.decode(str), publicKey);
                text.setText(new String(bs));
            }else {
                //私钥加密
                byte[] bs = RSACrypt.encryptByPrivateKey(data.getBytes(), privateKey);
                text.setText(RSACrypt.encode(bs));
            }
            isRSAEncrypt = !isRSAEncrypt;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 相关阅读:
    检验maven的配置是否生效或正确。
    CTO、技术总监和技术经理有啥区别?
    WinScp自动执行脚本
    宝塔--服务器运维面板
    Tomcat中给server.xml加入<Context>元素
    Tomcat之Session名称修改-springboot
    修改tomcat默认的session时间
    Shiro权限框架简单快速入门
    mybatis关联查询
    <mvc:default-servlet-handler/>导致controller失效,报404错误
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/6371632.html
Copyright © 2020-2023  润新知