很多人都用MD5+Base64方式存储密码,这种存储方式 方便、速度快而且由于MD5杂凑算法的几乎不可还原性,攻击者只能通过"猜"去破解密码。

但是MD5对相同的数据返回的信息永远是一样的,"123456"通过MD5+Base64编码后,永远是"4QrcOUm6Wau+VuBX8g+IPg==",攻击者只需要一个简单的sql语句:select * from userInfo where password='4QrcOUm6Wau+VuBX8g+IPg==' 就可以知道有几个用户密码是"123456",这对一个项目来说十分危险。

//这个循环无论执行几次,返回都是一样。static void t3(){for(int i=0;i<5;i++){try {String inputPwd = "123456";MessageDigest md;BASE64Encoder b64Encoder = new BASE64Encoder();byte[] bys = null;md = MessageDigest.getInstance("MD5","SUN");md.reset();md.update(inputPwd.getBytes("UTF-8"));bys = md.digest();System.out.println("编码后:"+b64Encoder.encode(bys));            } catch (Exception e) {e.printStackTrace();}}}

一种简单有效的解决方法,就是在MD5杂凑前加点随机码,这样攻击者将无法通过一个简单的SQL语句来查找密码是"123456"的用户。

随机码长度是应该固定,且同用户输入的密码一起进行MD5杂凑,随机码应该在Base64编码后的固定位置。

校验时,先取出随机码,再同输入一起进行MD5杂凑,与以前存储的密码比较是否一致。

package test1;import java.security.MessageDigest;
import java.util.Random;import sun.misc.BASE64Encoder;/*** 对帐号口令加密* @author shanl**/
public class PasswdEncryption {private static final MessageDigest md;private static final BASE64Encoder b64Encoder;static{try {md = MessageDigest.getInstance("MD5", "SUN");b64Encoder = new BASE64Encoder();} catch (Exception e) {throw new RuntimeException(e);}}/*** 检查密码* @param inputPasswd 用户输入的密码* @param storePasswd 已存储的密码* @return true:通过检查,false:未通过*/synchronizedpublic static boolean checkPasswd(String inputPasswd, String storePasswd){boolean ok = false;try{byte[] saltBys = storePasswd.substring(0,2).getBytes("UTF-8");String inPwd = toPasswd(inputPasswd, saltBys);ok = inPwd.equals(storePasswd);}catch(Exception ex){ex.printStackTrace();ok = false;}return ok;}/*** 将客户输入的密码加密* @param inputPasswd* @return*/synchronized public static String toPasswd(String inputPasswd){byte[] salt = getSaltOfASCII(2);return toPasswd(inputPasswd, salt);}/*** 将客户输入的密码加密* @param inputPasswd 客户输入的密码 * @param salt 盐* @return 加密后的字符串*/synchronizedprivate static String toPasswd(String inputPasswd, byte[] salt){String pwd = "";try{            md.reset();md.update(salt);md.update(inputPasswd.getBytes("UTF-8"));byte[] bys = md.digest();;//1:AASLexNtFtI7e1IuQIg88ZNA==//879:AA/lCM5NEwVQJ25YYomE1ldQ==//1000:AARXKQat7z+/iu2w6KpKgLQA==
//          for(int i=0; i<1000; i++){
//              md.reset();
//              bys = md.digest(bys);
//          }pwd += (char)salt[0];pwd += (char)salt[1];pwd += b64Encoder.encode(bys);         }catch(Exception ex){ex.printStackTrace();pwd = "";}return pwd;}/*** 返回指定长度的盐(ASCII码)* @param len 长度* @return*/private static byte[] getSaltOfASCII(int len){byte[] salt = new byte[len];Random rand = new Random();for(int i=0; i<len; i++){
//          salt[i] = 'A';salt[i] = (byte) ((rand.nextInt('~'-'!')+'!') & 0x007f);}return salt;}
}

测试类:

package test1;public class Test8 {public static void main(String[] args){t2();
//      t1();}static void t2(){String[] userPwds = {"123456","123456","123456","123456","123456","1234561", //error input};//通过t1()得到String[] dbPwds = {"u:rkoqEBZ+IZlcugSyVkhNVg==","vDEbVZ9JlSveGnB/Qdz69aAQ==","hbgon/TjwH8s7YSuqVSDl9Yg==","0-ExML8oTOSCeF3ETf1yvDHg==","1TeHpWiXOhx5ilscC6D6G98g==","1TeHpWiXOhx5ilscC6D6G98g==",};String msg = "";for(int i=0,end=dbPwds.length; i<end; i++){msg  = "user input passwd:"+userPwds[i];msg += ",db store passwd:"+dbPwds[i];msg += ",check passwd:"+PasswdEncryption.checkPasswd(userPwds[i],dbPwds[i]);System.out.println(msg);}}/*** 加密测试*/static void t1(){String pwd = "123456";String pwd1 = null;//PasswdEncryption.toPasswd(pwd);for(int i=0; i<5; i++){pwd1 = PasswdEncryption.toPasswd(pwd);System.out.println(pwd1);}}
}

t1()结果显示,在很小的情况下会出现相同的加密后密码,攻击者很难用一个简单SQL去查找同一密码的用户。

t2()则可以用同一个密码"123456"验证,多个加密后的密码。

密码和Java中的加解密之MD5加点盐相关推荐

  1. Java使用AES加解密

    Java使用AES加解密 目录 1.1生成密钥 1.2密钥的存储 1.3获取存储的密钥 1.4加解密 1.5使用存储的密钥进行加解密示例 AES是一种对称的加密算法,可基于相同的密钥进行加密和解密.J ...

  2. java实现DES加解密算法

    以下是我用java实现的DES算法,实现中可能存在一点问题自己没空去找,但我觉得DES的算法过程肯定没错!现在暂时没时间去找到底是哪里的问题,有空再瞧瞧自己的代码喽! makekey.java是生成密 ...

  3. 一个java的DES加解密类转换成C#

    原文:一个java的DES加解密类转换成C# 一个java的des加密解密代码如下: //package com.visionsky.util;import java.security.*; //im ...

  4. JAVA:实现XXTea加解密算法(附完整源码)

    JAVA:实现XXTea加解密算法 public class XXTEAprivate XXTEA() {}public static byte[] encrypt(byte[] data, byte

  5. Java中动态加载字节码的方法 (持续补充)

    文章目录 Java中动态加载字节码的方法 1.利用 URLClassLoader 加载远程class文件 2.利用 ClassLoader#defineClass 直接加载字节码 2.1 类加载 - ...

  6. 【AES256】Java实现AES256加解密

    AES256加解密比较常见,这里简单记录以供参考! 一.下载 官方JDK默认支持AES-128,在 1.8.0_151 和 1.8.0_152 版本之前,需要从Oracle官网下载安全JAR包方可支持 ...

  7. Java 进行 RSA 加解密时不得不考虑到的那些事儿

    1. 加密的系统不要具备解密的功能,否则 RSA 可能不太合适 公钥加密,私钥解密.加密的系统和解密的系统分开部署,加密的系统不应该同时具备解密的功能,这样即使黑客攻破了加密系统,他拿到的也只是一堆无 ...

  8. openssl c++实现bouncycastle中AES加解密

    0x01 为什么要用bouncycastle 先说说JCE(Java Cryptography Extension)是一组包,它们提供用于加密.密钥生成和协商以及 Message Authentica ...

  9. Java中3DES加密解密示例

    在java中调用sun公司提供的3DES加密解密算法时,需要使用到$JAVA_HOME/jre/lib/目录下如下的4个jar包: jce.jar security/US_export_policy. ...

最新文章

  1. 基于ASP.Net Core开发的一套通用后台框架
  2. git把本地代码上传(更新)到github上
  3. 在阿里淘系6个月能有哪些收获成长?
  4. 旅游系统_旅游标识系统,必须真的“旅游化”
  5. 前端复习之JavaScript基础
  6. matlab程序中中零内插在qdpsk调制中的作用,桂林电子科技大学通信原理思考题
  7. Linux 内核调试指南[转载]
  8. 【scratch音乐课】天空之城:音符与节拍、消息与链表
  9. 【Android工具】更新手机流媒体播放器,手机DLNA播放器OPlayer
  10. 四柱八字大全 php,四柱八字
  11. WEB安全(十六)单点登录的基本实现
  12. 安卓zip解压软件_手机压缩软件ZArchiver下载、使用教程丨免费、中文,支持7z、zip、rar等所有格式...
  13. 将iTunes降级到12.6版本
  14. 【pycharm】英文输入法变成全角字符无法输入
  15. 探究 | Elasticsearch如何物理删除给定期限的历史数据?
  16. 实现微信小程序web-view内嵌H5中的下载功能(大文件切片下载)
  17. 消灭泡泡糖游戏java编程_JAVA面向对象编程课程设计——泡泡堂
  18. w7计算机防火墙无法更改,w7防火墙无法更改该怎么办
  19. 西电硕士论文 Latex 模板:填坑!
  20. 登录界面及其功能的设计

热门文章

  1. ### Cause: java.sql.SQLSyntaxErrorException: ORA-00903: 表名无效
  2. 删除数组最后一个元素
  3. 秦羽接引的鸿蒙第四人,星辰变:仙界最强的五人,秦羽第二,敖无虚垫底,小黑难进前三...
  4. obs源码二次开发,自定义插入SEI
  5. 计算机学院陈宇,计算机学院学生社团联合会第一次全体会议顺利召开
  6. JavaScript小技能:客户端 API
  7. Java三个月速成学习路线图
  8. 3d游戏建模可以自学吗?小白教程
  9. if和for的几个经典题目
  10. 史上最详细的maven仓库详解