当前位置:   article > 正文

Java哈希算法总结_java 字符串hash

java 字符串hash

一、编码算法

编码是直接给每个字符指定一个若干字节表示的整数。

常见的编解码算法有:URL编码、Base64编码。

1、URL编码是浏览器发送数据给服务器时使用的编码。

特点:把数据编码成前缀为%表示的字符串。

URL编码对A(a)-Z(z),0-9, - , _ , . , * 这些字符不进行编码,除此以外的字符则需要进行编码。

URLEncoder类:对URL进行斑马操作的。

有编码必然有解码,URLDecoder类:对URL进行解码操作的。

 2.Base64编码:将字节数组编码成字符串或将字符串解码为字节数组

特点:把字符编码成%xx表示的形式。

 二、哈希算法

1、哈希算法又称摘要算法,作用是对任意一组输入数据进行计算,得到一个固定长度的输出摘要。

目的:验证原始数据是否被篡改。

2、哈希碰撞是指:两个不同的输入得到了相同的输出。

哈希碰撞不能避免,因为输出的字节长度是固定的,而且最多有4294967296中输出,但是有无限种输入。

3、常见的哈希算法:MD5算法,SHA-1(20字节),SHA-256(32字节),SHA-512(64字节),RipeMD-160算法(Java标准类库中没有提供RipeMD-160算法)。

MD5算法(长度:16字节)

 需要编写一个hash算法的工具类,定义bytesToHex()方法,将字节数组转换为十六进制字符串。

 SHA-1算法:与MD5使用方法一样,只用在实例化MessageDigest对象时将传入的参数改为"SHA-1"即可。

RipeMD160算法

  1. public class Demo03 {
  2. //使用第三方开源库提供的RipeMD160消息摘要算法实现
  3. public static void main(String[] args) throws NoSuchAlgorithmException {
  4. //注册BouncyCastleBouncyCastleProvider通知类
  5. //将提供的消息摘要算法注册至Security
  6. Security.addProvider(new BouncyCastleProvider());
  7. //获取RipeMD160算法的“消息摘要对象”(加密对象)
  8. MessageDigest ripeMd160 = MessageDigest.getInstance("RipeMD160");
  9. //更新原始数据
  10. ripeMd160.update("wbjxxmy".getBytes());
  11. //获取消息摘要(加密)
  12. byte[] result = ripeMd160.digest();
  13. //消息摘要的字节长度和内容
  14. System.out.println("加密结果(字节长度):"+result.length);//160位=20字节
  15. System.out.println("加密结果(字节内容):"+Arrays.toString(result));
  16. //16进制内容字符串
  17. String hex = new BigInteger(1,result).toString(16);
  18. System.out.println("加密结果(字符串长度):"+hex.length());
  19. System.out.println("加密结果(字符串内容):"+hex);
  20. }
  21. }

4.存储用户密码

如果直接将用户的密码不做任何处理直接放入数据库中,会存在很大的安全风险。所以改进方法是存储用户密码的哈希。

什么是彩虹表攻击?例如:使用MD5。就是将常用口令和它们MD5制作成一张表(这个表足够庞大),这个表就是彩虹表。为了防止彩虹表攻击,对每个口令前面追加一些额外的数字,这就是盐值。

 5.解决MD5算法与SHA-1算法代码冗余

  1. //hash算法工具类
  2. public class HashTools {
  3. //定义全局变量,消息摘要对象
  4. private static MessageDigest digest;
  5. //构造方法私有
  6. private HashTools() {}
  7. //按照MD5进行消息摘要算法(哈希计算)
  8. public static String digestByMD5(String source) throws NoSuchAlgorithmException {
  9. //基于MD5算法
  10. digest = MessageDigest.getInstance("MD5");
  11. return handler(source);
  12. }
  13. //按照SHA-1进行消息摘要算法(哈希计算)
  14. public static String digestBySHA1(String source) throws NoSuchAlgorithmException {
  15. //基于SHA-1算法
  16. digest = MessageDigest.getInstance("SHA-1");
  17. return handler(source);
  18. }
  19. //通过消息摘要对象,处理加密内容
  20. private static String handler(String source) {
  21. //更新原始数据
  22. digest.update(source.getBytes());
  23. //进行加密处理
  24. byte[] bytes = digest.digest();
  25. //将字节数组转换成十六进制
  26. String hash = bytesToHex(bytes);
  27. return hash;
  28. }
  29. //将字节数组转换为16进制字符串
  30. public static String bytesToHex(byte[] bytes) {
  31. StringBuilder ret = new StringBuilder();
  32. for(Byte b : bytes) {
  33. //将字节值转换为2位十六进制字符串
  34. ret.append(String.format("%02x", b));
  35. }
  36. return ret.toString();
  37. }
  38. }

三、Hmac算法

Hmac算法:基于秘钥的消息摘要算法.也是一种防御彩虹表攻击的算法,它比"加盐"这种方式的安全性更高。

1、使用秘钥生成器生成秘钥,进行加密处理

  1. public class Demo01 {
  2. public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
  3. String password = "wbjxxmy";
  4. //1.产生秘钥
  5. //获取HmacMD5秘钥生成器
  6. KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
  7. //生成密钥
  8. SecretKey key = keyGen.generateKey();
  9. System.out.println("秘钥:"+Arrays.toString(key.getEncoded()));
  10. System.out.println("秘钥长度(64字节):"+key.getEncoded().length);
  11. System.out.println("秘钥:"+HashTools.bytesToHex(key.getEncoded()));
  12. //2.使用秘钥,进行加密
  13. //获取HMac加密算法
  14. //创建Mac对象,传入"HmacMD5"算法
  15. Mac mac = Mac.getInstance("HmacMD5");
  16. //初始化秘钥
  17. mac.init(key);
  18. //更新原始加密内容
  19. mac.update(password.getBytes());
  20. //加密处理,并获取加密结果
  21. byte[] bytes = mac.doFinal();
  22. //加密结果处理成16进制字符串
  23. String result = HashTools.bytesToHex(bytes);
  24. System.out.println("加密结果16进制字符串:"+result);
  25. System.out.println("加密结果(字节长度16字节):"+bytes.length);
  26. System.out.println("加密结果(字符长度32字节):"+result.length());
  27. }
  28. }

2、给定秘钥字节数组,恢复Hmac秘钥

给定一个秘钥字节数组,先将其恢复成秘钥对象,再进行加密处理。

  1. //秘钥(字节数组)
  2. byte[] keyBytes = {51, 8, 87, 91, 106, -78, 70, -119, 5, -75, 78, -52, -62, -33,
  3. -64, -102, 80, 56, 7, -43, -115, 57, 29, 69, -61, 121, -37, -47, -95,
  4. 66, -82, -116, -22, 19, -8, -42, 127, 67, 18, -109, -9, 89, 7, 6, 59,
  5. -63, 51, 35, 0, 45, -102, -20, -82, -82, 29, -105, 10, 0, -110, -70, 76,
  6. -102, -57, 50};
  7. try {
  8. //恢复秘钥(字节数组)
  9. SecretKey key = new SecretKeySpec(keyBytes, "HmacMD5");
  10. //创建Hmac加密算法对象
  11. Mac mac = Mac.getInstance("HmacMD5");
  12. //初始化秘钥
  13. mac.init(key);
  14. //更新原始加密内容
  15. mac.update(password.getBytes());
  16. //加密结果处理成16进制字符串
  17. String result = HashTools.bytesToHex(mac.doFinal());
  18. //输出
  19. System.out.println(result);
  20. } catch (NoSuchAlgorithmException e) {
  21. e.printStackTrace();
  22. } catch (InvalidKeyException e) {
  23. e.printStackTrace();
  24. }

3、按照"字符串",恢复Hmac秘钥

先将字符串转换成字节数组再进行后续步骤。

  1. //秘钥(字符串)
  2. String keyStr = "1dbb7361d48949df91e3ff0c5fab8666c5358a8daf965d6"
  3. + "bbd84ff90e17c3a365b2c6613ac257ae961d75402e88d47c6a0854de60cde"
  4. + "00.070982b3e437e4dec91af";
  5. //用于保存秘钥,秘钥长度为64字节
  6. byte[] keyBytes = new byte[64];
  7. //遍历字符串,将其保存进字节数组keyBytes中
  8. for(int i = 0,k = 0;i < keyStr.length();i += 2,k++) {
  9. //每次截取两位
  10. String s = keyStr.substring(i,i+2);
  11. //将截取的两位字符转换成16进制,放入字节数组中
  12. keyBytes[k] = (byte) Integer.parseInt(s,16);
  13. }
  14. try {
  15. //恢复秘钥(字节数组)
  16. SecretKey key = new SecretKeySpec(keyBytes, "HmacMD5");
  17. //创建Hmac加密算法对象
  18. Mac mac = Mac.getInstance("HmacMD5");
  19. //初始化秘钥
  20. mac.init(key);
  21. //更新原始加密内容
  22. mac.update(password.getBytes());
  23. //加密结果处理成16进制字符串
  24. String result = HashTools.bytesToHex(mac.doFinal());
  25. //输出
  26. System.out.println(result);
  27. } catch (NoSuchAlgorithmException e) {
  28. e.printStackTrace();
  29. } catch (InvalidKeyException e) {
  30. e.printStackTrace();
  31. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号