今天去门买饭的时候和某人聊起关于密码的话题,不知道大家有没有这样想过,为什么当我们忘记自己某个通行证密码的时候,比如QQ密码,邮箱密码,微博密码,是要通过修改密码去取得一个新的密码,而不是直接告诉你原密码呢,当然这里并不是因为权限的问题,因为直接告诉你密码也可以是在一系列的验证之后。
真正的原因是其实服务商也不知道你的原密码是什么!我想很多人现在会唏嘘不已,那服务商是如何验证我的密码是否和用户名相对应的呢。
在这之前,请先让我普及一些关于密码的常识。平时我们所说的密码实际上是明文,也叫明码,比如QQ密码是:1234abc,这个明码经过特定的算法加密后就变成了真正的密码,也叫密文。
现在情况又比较明朗了吧,真正的过程是这样的:明文密码->加密算法->密文密码->存储。服务商的数据库里所存储的是你的密文密码,而现在普通的密码存储都是采用MD5算法(其实严格来讲MD5并不是一种加密算法),MD5算法最大的特点就是单向加密,通过加密后变成一串32位的字符串,然后存储在数据库里。
每次你需要密码验证的时候,服务商把你当前所填的密码进行加密后所得到的字符串去和数据库里所存储的字符串进行比对,完全匹配后说明你当前输入的密码即为你原来的密码。因为MD5算法在数学上可以证明加密前的明文和加密后的密文是唯一对应的。正因为如此,当你密码忘记的时候,服务商是不可能告诉你原密码的,只能通过修改密码来获取一个新的密码。当然还有一种情况就是服务商会帮你重置一个新的密码,然后告诉你,叫你尽快去修改,当然这里只是权限的问题。
至于为什么要设计成单向加密,密文存储,原因很简单,当存储用户资料(用户名,密码)的数据库被恶意攻击或窃取时,如果存储的是明文密码,后果可想而知,而如果不采用单向加密的话,只要一个简单的逆向解密算法,也是可以把存储的信息转为用户的密码。史上著名的优快云密码泄露事件就是因为2009年之前用户的密码都是明文存储,在数据库迁移的时候被泄露。
下面我来演示下如何用java自带的开发包来实现这个MD5加密算法的。
import java.security.MessageDigest;
public class Test
{
public static String md5(String input)
{
StringBuffer total = new StringBuffer();
try{
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] inputs = input.getBytes();
md5.update(inputs);
byte[] out = md5.digest();
for(int i = 0; i<16; i++){
String temp = Integer.toHexString(out[i]);
if(out[i] < 0){
temp = temp.substring(6);
}
if(temp.length() == 1){
temp = '0' + temp;
}
total.append(temp);
}
}
catch (Exception localException){
}
return total.toString();
}
public static void main(String agrs[])
{
Test t = new Test();
System.out.println(t.md5("Hello World!"));
}
}
输出的结果:
即Hello World!这个字符串进行加密后的32位字符串是:ed076287532e86365e841e92bfc50d8c
哈哈,现在我来测测我的QQ密码加密后的密文是什么:
当然明文是不会告诉你们的啦。