PBKDF2 java加密与解密

1public class suanfa { 2 public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException 3 { 4 String originalPassword = "123456"; 5 String generatedSecuredPasswordHash = generateStorngPasswordHash(originalPassword); 6 System.out.println(generatedSecuredPasswordHash); 7 8 boolean matched = validatePassword("123456", generatedSecuredPasswordHash); 9 System.out.println(matched); 10 11 matched = validatePassword("password1", generatedSecuredPasswordHash); 12 System.out.println(matched); 13 } 14 15 private static boolean validatePassword(String originalPassword, String storedPassword) throws NoSuchAlgorithmException, InvalidKeySpecException 16 { 17 String[] parts = storedPassword.split(":"); 18 int iterations = Integer.parseInt(parts[0]); 19 byte[] salt = fromHex(parts[1]); 20 byte[] hash = fromHex(parts[2]); 21 22 PBEKeySpec spec = new PBEKeySpec(originalPassword.toCharArray(), salt, iterations, hash.length * 8); 23 SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 24 byte[] testHash = skf.generateSecret(spec).getEncoded(); 25 26 int diff = hash.length ^ testHash.length; 27 for(int i = 0; i < hash.length && i < testHash.length; i++) 28 { 29 diff |= hash[i] ^ testHash[i]; 30 } 31 return diff == 0; 32 } 33 34 private static byte[] fromHex(String hex) throws NoSuchAlgorithmException 35 { 36 byte[] bytes = new byte[hex.length() / 2]; 37 for(int i = 0; i<bytes.length ;i++) 38 { 39 bytes[i] = (byte)Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); 40 } 41 return bytes; 42 } 43 44 private static String generateStorngPasswordHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException 45 { 46 int iterations = 147852; 47 char[] chars = password.toCharArray(); 48 byte[] salt = getSalt().getBytes(); 49 50 PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 64 * 8); 51 SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 52 byte[] hash = skf.generateSecret(spec).getEncoded(); 53 return iterations + ":" + toHex(salt) + ":" + toHex(hash); 54 } 55 56 private static String getSalt() throws NoSuchAlgorithmException 57 { 58 SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 59 byte[] salt = new byte[16]; 60 sr.nextBytes(salt); 61 return salt.toString(); 62 } 63 64 private static String toHex(byte[] array) throws NoSuchAlgorithmException 65 { 66 BigInteger bi = new BigInteger(1, array); 67 String hex = bi.toString(16); 68 int paddingLength = (array.length * 2) - hex.length(); 69 if(paddingLength > 0) 70 { 71 return String.format("%0" +paddingLength + "d", 0) + hex; 72 }else{ 73 return hex; 74 } 75 } 76}

较高密码安全实现使用 PBKDF2WithHmacSHA1 算法

到目前为止,我们已经了解如何为密码生成安全的 Hash 值以及通过利用 salt 来加强它的安全性。但今天的问题是,硬件的速度已经远远超过任何使用字典或彩虹表进行的暴力攻击,并且任何密码都能被破解,只是使用时间多少的问题。

为了解决这个问题,主要想法是尽可能降低暴力攻击速度来保证最小化的损失。我们下一个算法同样是基于这个概念。目标是使 Hash 函数足够慢以妨碍攻击,并对用户来说仍然非常快且不会感到有明显的延时。

要达到这个目的通常是使用某些 CPU 密集型算法来实现,比如 PBKDF2, Bcrypt 或 Scrypt 。这些算法采用 work factor(也称之为 security factor)或迭代次数作为参数来确定 Hash 函数将变的有多慢,并且随着日后计算能力的提高,可以逐步增大 work factor 来使之与计算能力达到平衡。

更加安全的密码实现使用 bcrypt 和 scrypt 算法

bcrypt 的背后的思想与 PBKDF2 类似。只是 Java 中并没有内置支持使攻击者变慢的 bcrypt 算法实现,但你仍然可以找到并下载它的源码。

//加盐  可变的 随机的  长度不能过短

最后说明

  1. 在应用程序中存储密码明文是极其危险的事情。
  2. MD5 提供了最基本的安全 Hash 生成,使用时应为其添加 slat 来进一步加强它的安全性。
  3. MD5 生成128位的 Hash。为了使它更安全,应该使用 SHA 算法生成 160-bit 或 512-bit 的长 Hash,其中 512-bit 是最强的。
  4. 虽然使用 SHA Hash 密码也能被当今快速的硬件破解,如要避免这一点,你需要的算法是能让暴力攻击尽可能的变慢且使影响减至最低。这时候你可以使用 PBKDF2, BCrypt 或 SCrypt 算法。
  5. 请在深思熟虑后来选择适当的安全算法。

参考资料:

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang

java中使用redis

1.java代码publicclassRedisTest01{publicstaticvoidmain(Stringargs){//connectredisserverJedisredisnewJedis("127.0.0

javaSHA1实现加密解密

封装一个方法用于加密/sha1加密@paramdata@return@throwsNoSuchAlgorithmException/publicstaticStringsha1(Stri