哈希算法和·Hmac算法 对称式与非对称式加密对比

哈希算法( Hash )又称摘要算法( Digest ),

作用:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。 哈希算法的目的:为了验证原始数据是否被篡改。 哈希算法最重要的特点就是: 相同的输入一定得到相同的输出; 不同的输入大概率得到不同的输出。

 Java字符串的 hashCode() 就是一个哈希算法,它的输入是任意字符串,输出是固定的 4 字节 int 整数

"hello".hashCode(); // 0x5e918d2
"hello, java".hashCode(); // 0x7a9d88e8
"hello, bob".hashCode(); // 0xa0dbae2f

两个相同的字符串永远会计算出相同的 hashCode ,否则基于 hashCode 定位的 HashMap 就无法正常工作。这也是为什么当我们自定义 一个 class 时,覆写 equals() 方法时我们必须正确覆写 hashCode() 方法。

哈希冲突:两个不同的内容却又相同的哈希值:

"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0

"通话".hashCode(); // 0x11ff03
"重地".hashCode(); // 0x11ff03

 为了避免碰撞我们输出的长度越长越好:

Java 标准库提供了常用的哈希算法,并且有一套统一的接口。我们以 MD5 算法为例,看看如何对输入计算哈希:

import java.security.MessageDigest;

public class main {
	public static void main(String[] args)  {
		// 创建一个MessageDigest实例:
        MessageDigest md = MessageDigest.getInstance("MD5");
       
        // 反复调用update输入数据:
        md.update("Hello".getBytes("UTF-8"));
        md.update("World".getBytes("UTF-8"));
        
        // 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
        byte[] results = md.digest(); 

        StringBuilder sb = new StringBuilder();
        for(byte bite : results) {
        	sb.append(String.format("%02x", bite));
        }
        
        System.out.println(sb.toString());
	}
}

使用 MessageDigest 时,我们首先根据哈希算法获取一个 MessageDigest 实例,然后,反复调用 update(byte[]) 输入数据。当输入 结束后,调用 digest() 方法获得 byte[] 数组表示的摘要,最后,把它转换为十六进制的字符串。 运行上述代码,可以得到输入 HelloWorld 的 MD5 是 68e109f0f40ca72a15e05cc22786f8e6 。

MD5:

可以校验下载文件是否为原本文件;

可以存储数据库的密码,这样一来,数据库管理员看不到用户的原始口令。即使数据库泄漏,黑客也无法拿到用户的原始口令。想要拿到用户的原始口令,必须 用暴力穷举的方法,一个口令一个口令地试,直到某个口令计算的 MD5 恰好等于指定值。 使用哈希口令时,还要注意防止彩虹表攻击。什么是彩虹表呢?上面讲到了,如果只拿到 MD5 ,从 MD5 反推明文口令,只能使 用暴力穷举的方法。然而黑客并不笨,暴力穷举会消耗大量的算力和时间。但是,如果有一个预先计算好的常用口令和它们的 MD5 的 对照表,这个表就是彩虹表。如果用户使用了常用口令,黑客从 MD5 一下就能反查到原始口令

所以我们可以进行添加操作:使用SHA-1 也是一种哈希算法,它的输出是 160 bits ,即 20 字节。 SHA-1 是由美国国家安全局开发的, SHA 算法实际上是一个系列,包括 SH A-0 (已废弃)、 SHA-1 、 SHA-256 、 SHA-512 等。

import java.security.MessageDigest;

public class main {
	public static void main(String[] args)  {
		// 创建一个MessageDigest实例:
        MessageDigest md = MessageDigest.getInstance("SHA-1");
       
        // 反复调用update输入数据:
        md.update("Hello".getBytes("UTF-8"));
        md.update("World".getBytes("UTF-8"));
        
        // 20 bytes: db8ac1c259eb89d4a131b253bacfca5f319d54f2
        byte[] results = md.digest(); 

        StringBuilder sb = new StringBuilder();
        for(byte bite : results) {
        	sb.append(String.format("%02x", bite));
        
  • 126
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大西瓜写java、C#、.NET

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值