【Java教程】Day14-02 加密与安全:哈希算法

打印 上一主题 下一主题

主题 878|帖子 878|积分 2634

哈希算法(Hash),又称择要算法(Digest),广泛用于数据完备性校验、密码学应用以及快速数据查找等场景。本文将深入先容哈希算法的基本原理、常用算法、在Java中的实现及其应用场景。
1. 哈希算法概述

哈希算法的焦点作用是将恣意输入数据通过特定算法计算后,天生一个固定长度的输出值,通常称为“择要”。哈希算法的告急特点包括:


  • 相同的输入,得到相同的输出
  • 不同的输入,大概率得到不同的输出
哈希算法的主要目的是验证数据是否被窜改。它广泛应用于文件校验、数字签名、数据去重等领域。


2. Java中的哈希算法:hashCode()与自定义实现

Java提供了字符串的hashCode()方法,这也是一种哈希算法。该方法的输入为恣意字符串,输出为一个固定的4字节(32位)整数。例如:
  1. java"hello".hashCode();        // 输出: 0x5e918d2"hello, java".hashCode();  // 输出: 0x7a9d88e8"hello, bob".hashCode();   // 输出: 0xa0dbae2f
复制代码
在Java中,hashCode()是哈希算法的一种应用,特殊在HashMap等基于哈希的数据结构中,它用于确定命据存储位置。
2.1 哈希碰撞

哈希碰撞是指不同的输入数据天生相同的哈希值。例如:
  1. java"AaAaAa".hashCode();  // 输出: 0x7460e8c0"BBAaBB".hashCode();  // 输出: 0x7460e8c0
复制代码
由于哈希值是有限长度的(如Java的hashCode()输出为4字节,最大值为4294967296种可能的输出),但输入数据可以是恣意长度,肯定存在碰撞的情况。因此,哈希算法的设计需要尽量减少碰撞的发生概率,特殊是在需要保证安全性的场景中。


3. 安全性要求

一个好的哈希算法必须满足以下两个安全性要求:

  • 碰撞概率低:即尽可能避免不同输入天生相同的哈希值。
  • 不可预测性:输出值的厘革应该是不可预测的,输入数据的微小厘革应该导致输出值的巨大差异。例如,若输入数据从“java001”厘革为“java002”,则哈希输出应完全不同。


4. 常见哈希算法

常用的哈希算法包括:
算法输出长度(位)输出长度(字节)MD5128 bits16 bytesSHA-1160 bits20 bytesSHA-256256 bits32 bytesSHA-512512 bits64 bytes 4.1 MD5算法

MD5是一种常见的哈希算法,输出长度为128位(16字节)。固然MD5曾广泛应用于文件校验和密码存储,但由于其较短的输出长度,已经不再推荐用于需要高安全性的场景。
4.2 SHA-1与SHA-256

SHA系列算法由美国国家安全局(NSA)开发,SHA-1和SHA-256是较常用的版本,分别输出160位(20字节)和256位(32字节)。SHA-256相比SHA-1更为安全。


5. 在Java中实现哈希算法

Java标准库提供了MessageDigest类来实现各种哈希算法。以下是一个计算MD5哈希的示例:
5.1 MD5哈希示例

  1. javaimport java.security.MessageDigest;import java.util.HexFormat;​public class Main {    public static void main(String[] args) throws Exception {        // 创建一个MessageDigest实例,指定哈希算法为MD5        MessageDigest md = MessageDigest.getInstance("MD5");                // 输入数据        md.update("Hello".getBytes("UTF-8"));        md.update("World".getBytes("UTF-8"));                // 计算哈希值        byte[] result = md.digest(); // 输出: 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6                // 输出为十六进制字符串        System.out.println(HexFormat.of().formatHex(result));    }}
复制代码
在这个例子中,我们使用了MessageDigest来计算“HelloWorld”字符串的MD5哈希,终极输出效果为:68e109f0f40ca72a15e05cc22786f8e6。
5.2 SHA-1与SHA-256示例

计算SHA-1和SHA-256的过程与MD5类似,只需将算法名称改为"SHA-1"或"SHA-256":
  1. java// 计算SHA-1MessageDigest md1 = MessageDigest.getInstance("SHA-1");md1.update("HelloWorld".getBytes("UTF-8"));byte[] sha1Result = md1.digest();System.out.println(HexFormat.of().formatHex(sha1Result));​// 计算SHA-256MessageDigest md2 = MessageDigest.getInstance("SHA-256");md2.update("HelloWorld".getBytes("UTF-8"));byte[] sha256Result = md2.digest();System.out.println(HexFormat.of().formatHex(sha256Result));
复制代码

6. 哈希算法的应用

6.1 校验数据完备性

哈希算法常用于文件校验。在下载软件或文件时,官网通常会提供文件的哈希值,用户可以计算当地文件的哈希值并与官网提供的哈希值进行对比。假如两个哈希值相同,则证明文件未被窜改。
6.2 存储用户密码

直接存储明文密码会存在极大安全隐患。为了提高安全性,密码可以通过哈希算法存储。常用的方法是对用户的密码进行哈希处理,存储哈希值而非明文密码。
例如,数据库中存储用户的哈希值:
用户名密码哈希值bobf30aa7a662c728b7407c54ae6bfd27d1alice25d55ad283aa400af464c76d713c07ad 用户登录时,系统会将输入的密码进行哈希并与数据库中的哈希值进行比力。
6.3 防止彩虹表攻击

彩虹表是一种通过预计算大量常见密码的哈希值来加速破解的技能。为了防止这种攻击,可以采取“加盐”技能,即在密码哈希时添加随机数(盐)进行混淆。
例如:
  1. java// 对密码进行加盐处理String salt = "H1r0a";String saltedPassword = salt + userPassword;MessageDigest md5WithSalt = MessageDigest.getInstance("MD5");md5WithSalt.update(saltedPassword.getBytes("UTF-8"));byte[] saltedHash = md5WithSalt.digest();
复制代码
使用加盐后,即使用户使用常见密码,彩虹表攻击也无效。


7. 小结



  • 哈希算法用于数据完备性验证,广泛应用于密码学、文件校验等场景。
  • 常见的哈希算法有MD5、SHA-1、SHA-256等,选择时应根据安全性需求思量输出长度。
  • 使用哈希存储密码时,需要防止彩虹表攻击,方法是对密码进行加盐处理。

通过本文的先容,相信你对哈希算法有了更深入的理解,并能在Java中实现常见的哈希算法。假如你对密码学或数据安全感兴趣,进一步探索哈希算法的更多应用将对你有所帮助!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南飓风

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表