上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符串(消息摘要).

简单了解

  MD5(Message Digest Algorithm 5),翻译过来是消息摘要算法第五版,按照惯例,我们推理可能也有MD2,MD3这样名字的历史版本..

  即使完全不了解这个算法的原理,我们也可以从命名中看出一些眉道,所谓摘要,就是一个简短的概括,像我写过的毕业论文,上来第一部分就是摘要,它对后面长篇大论的文章做了一个简短有力的概括,其实MD5的作用也有点这样的味道,我们来看一段关于描述MD5算法作用的文字:

  MD5的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数),它主要用于确保数据传输的完整性和一致性.

  假设A要给远方的B发送一个文本文件,有100万字,当B收到文件的时候,该怎么知道这个文件在传过来的途中有没有被篡改呢,要是有人中途截断并篡改了文件内容那就不太妙了,这时候MD5就派上用场了,不管多大的文件,通过MD5加密之后都会得到一个定长的字符串,一般是32位,这时候A先对文件用MD5加密一下,得到的一串密文顺便也传给B,当B收到后文件,同样对文件用MD5加密一下,看看得到的密文是否和A传过来的一致,如果一致,说明这个文件是安全的.这样就确保了数据传输的完整性.

  事实上,我们从网络上下载文件的时候,有时候下载的文件后面都有一段MD5的密文,比如 MD5(e8027a87676ea48b3a3c9b0a4d8d87a0),作用和上面我举得例子类似(我觉得是这样....).

  MD5是一种公开的不可逆的算法,意味着是没有办法直接破解密文得到源数据信息的,md5可以对一个对一个任意大小的文件进行哈希运算,得到一个唯一的32位字符串.

  简单了解了MD5的功能,就可以直接看代码了.

java代码实现MD5

package com.wang.encryption;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.MessageDigest;
/**
* @author yogo.wang
* @date 2016/11/04-下午1:02.
*/
public class MD5Test {
public static String md5Encode(String msg) throws Exception{ byte[] msgBytes = msg.getBytes("utf-8");
/**
* 声明使用Md5算法,获得MessaDigest对象
*/
MessageDigest md5 = MessageDigest.getInstance("MD5");
/**
* 使用指定的字节更新摘要
*/
md5.update(msgBytes);
/**
* 完成哈希计算,获得密文
*/
byte[] digest = md5.digest();
/**
* 以上两行代码等同于 byte[] digest = md5.digest(msgBytes);
*/
return bytesToHexString(digest);
}
/**
* 将byte数组转化为16进制字符串形式
* @param bys
* @return
*/
public static String byteArr2hexString(byte[] bys){
StringBuffer hexVal=new StringBuffer();
int val=0;
for (int i = 0; i < bys.length; i++) {
//将byte转化为int 如果byte是一个负数就必须要和16进制的0xff做一次与运算
val=((int)bys[i]) & 0xff;
if(val<16){
hexVal.append("0");
}
hexVal.append(Integer.toHexString(val));
} return hexVal.toString(); } public static void main(String[] args) throws Exception {
String msg="helloworld";
String result=md5Encode(msg);
String result1=md5Encode(msg);
System.out.println(result);
System.out.println(result1);
} }

运行代码,得到的输出结果如下:

fc5e038d38a57032085441e7fe7010b0
fc5e038d38a57032085441e7fe7010b0

  可见,对同一个字段进行加密,得到的密文总是一致的.接下来看一下MD5实现的原理和应用.

MD5实现原理及应用  

  我看了一些网上的朋友自己实现的md5哈希的代码,只能说半知半解,这里贴一下,网络上的一些实现的步骤介绍(随便看看就好).

MD5算法的原理主要分为以下几个步骤,

  1)填充:首先将输入信息的长度(bit)进行填充,使得对512求余的结果等于448。填充的方法是填充一个1和n个0。

  2)记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

  3)装入标准的幻数:标准的幻数是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。

  4)四轮循环运算:循环的次数是分组的个数(N+1)。

  这里主要介绍一下,java中MessageDigest这个类,查看jdk的开发文档,可以看到该类位于java.security包下,文档对MessageDigest的描述如下:

public abstract class MessageDigest

extends MessageDigestSpi

此 MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。

MessageDigest 对象开始被初始化。该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算。

对于给定数量的更新数据,digest 方法只能被调用一次。digest 被调用后,MessageDigest 对象被重新设置成其初始状态。

实现可随意选择是否实现 Cloneable 接口。客户端应用程可以通过尝试复制和捕获 CloneNotSupportedException 测试可复制性:

MessageDigest md = MessageDigest.getInstance("SHA");

try {

md.update(toChapter1);

MessageDigest tc1 = md.clone();

byte[] toChapter1Digest = tc1.digest();

md.update(toChapter2);

...etc.

} catch (CloneNotSupportedException cnse) {

throw new DigestException("couldn't make digest of partial content");

}

注意,如果给定的实现是不可复制的,而事先已知摘要的数目,则仍然能够通过实例化几个实例计算中间摘要。

  主要方法的作用,在上面代码的注释中已经给出,这里就不在介绍了.

  MD5的应用领域主要可以分为以下几类:

1、防止被篡改(文件完整性验证),比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。

2、防止直接看到明文(口令加密),现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码。

3、防止抵赖(数字签名),例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。这样可以防止出现以后A不承认此事而带来的麻烦。

  虽然MD5是一种不可逆的算法,但并不意味着不可破解,大多数用户设置密码时都会使用比较有特殊意义的字段,比如生日,名字简拼,等,如果我把你的相关的信息,猜测出你可能会使用的密码,然后把他们都用MD5加密一遍,就得到很多个密文,再拿到你的密码的密文和我的密文库里一一对比,如果密文能匹配,那么你的密码本身也就不攻自破了.同样的道理,现在有很多网站有提供了一些在线的MD5值查询功能,输入MD5密码值后,如果在数据库中存在,那么可以很快获取其密码值,道理也是一样的,比如上面代码中我是对"helloworld"这个字符串进行MD5加密,理论上你只知道密文是不可能破解我的原始数据的,但事实上真的是这样吗? 来看一个网站http://pmd5.com/

 

  我输入上面代码生成的密文之后,网站一下子就破解了,原理也就很简单了.

  关于MD5更详细的文字资料,可以移步百度百科,介绍的挺详细的,值得一看. 

相关链接

  "java加密算法小结--Base64算法"

java单向加密算法小结(2)--MD5哈希算法的更多相关文章

  1. java单向加密算法小结(1)--Base64算法

    从这一篇起整理一下常见的加密算法以及在java中使用的demo,首先从最简单的开始. 简单了解 Base64严格来说并不是一种加密算法,而是一种编码/解码的实现方式. 我们都知道,数据在计算机网络之间 ...

  2. MD5哈希算法及其原理

    - MD5功能 MD5算法对任意长度的消息输入,产生一个128位(16字节)的哈希结构输出.在处理过程中,以512位输入数据块为单位. - MD5用途及特征 MD5通常应用在以下场景: 1.防篡改,保 ...

  3. 常用加密算法的Java实现(一) ——单向加密算法MD5和SHA

    1.Java的安全体系架构 1.1           Java的安全体系架构介绍 Java中为安全框架提供类和接口.JDK 安全 API 是 Java 编程语言的核心 API,位于 java.sec ...

  4. Java的单向加密算法MD5和SHA——加密和解密

    出自:http://www.cnblogs.com/onetwo/p/3875551.html 1.JDK中MD5和SHA加密的主要类 在JDK6.0中,与MD5与SHA密切相关的几个类的类图如下:  ...

  5. Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC

    Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC 博客分类: Java/Security Javabase64macmd5sha     加密解密,曾经是我一 ...

  6. BASE64与单向加密算法MD5&SHA&MAC

    言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书.     如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Diges ...

  7. Java 对字符串数据进行MD5/SHA1哈希散列运算

    Java对字符串数据进行MD5/SHA1哈希散列运算 [java] view plain copy package cn.aibo.test; import java.security.Message ...

  8. java基本加密算法

    简单的java加密算法有: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algor ...

  9. java常用加密算法

    常用加密算法的Java实现(一) ——单向加密算法MD5和SHA 日期:2014/6/1 文:阿蜜果 1.Java的安全体系架构 1.1           Java的安全体系架构介绍 Java中为安 ...

随机推荐

  1. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  2. 菜鸟学Struts2——Struts工作原理

    在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...

  3. Minor【 PHP框架】1.简介

    1.1 Minor是什么 Minor是一个简单但是优秀的符合PSR4的PHP框架,It just did what a framework should do. 只做一个框架应该做的,简单而又强大! ...

  4. C#基础篇 - 正则表达式入门

    1.基本概念 正则表达式(Regular Expression)就是用事先定义好的一些特定字符(元字符)或普通字符.及这些字符的组合,组成一个“规则字符串”,这个“规则字符串”用来判断我们给定的字符串 ...

  5. CentOS7 重置root密码

    1- 在启动grub菜单,选择编辑选项启动 2 - 按键盘e键,来进入编辑界面 3 - 找到Linux 16的那一行,将ro改为rw init=/sysroot/bin/sh 4 - 现在按下 Con ...

  6. Linux学习之探索文件系统

    Linux,一起学习进步-    ls With it, we can see directory contents and determine a variety of important file ...

  7. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  8. Android 开发一定要看的15个实战项目

    前言: 虽说网上有太多的Android课程,但是大多都是视频,有Android在线开发环境的几乎没有,但是对于学习Android的人来说拥有在线的Android开发环境是非常好的,可以随时动手操作学习 ...

  9. Openfire阶段实践总结

    从3月开始研究Openfire,其实就是要做一套IM系统,也正是这个原因才了解到Openfire.之前还真没想过有这么多的开源产品可以做IM,而且也没想到XMPP这个协议竟然如何强大.看来还是标准为先 ...

  10. Egret3D研究报告(二)从Unity3D导出场景到Egret3D

    Egret3D暂时没有场编的计划,但是我们知道unity3D是一个很好的场编. 有一些游戏即使不是使用Unity3D开发,也使用Unity3D做场编.这里就不点名了,而且并不在少数. 我们就这么干. ...