哈希算法及加密实现


前言

哈希算法被广泛运用在各种途径中,本文章将带你初步认识哈希算法及它的加密的实现操作效果。


一、哈希算法是什么?

哈希算法又称摘要算法(Disgest),一般指SHA家族,它是安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

哈希算法特点

  • 相同的输入一定得到相同的输出
  • 不同的输入大概率得到不同的输出
    因此,哈希算法的目的是验证原始数据是否被篡改
    我们可以调用java的hashCode方法验证
System.out.println("Hello Java".hashCode());// 387417328
System.out.println("Hello java".hashCode());// 388370640
System.out.println("Hello,bob".hashCode());//-1095500357

哈希碰撞

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

	String s1 = "通话";
	String s2 = "重地";
	System.out.println(s1.hashCode());// 1179395
	System.out.println(s2.hashCode());// 1179395

哈希碰撞是不能避免的,这是因为输出的字节长度是固定的,但输入的字节长度不固定,有无数种输入,所以哈希算法是把无数的输入集合映射到一个有限的输出集合里,必然会产生碰撞。
既然不能避免碰撞,我们就要想办法降低碰撞的概率,提高哈希算法的安全性,所以一个安全的哈希算法必须满足:

  • 碰撞概率低
  • 不能被预测输出

常用的哈希算法

算法输出长度(位)输出长度(字节)
MD5128bits16bytes
SHA-1160bits20bytes
RipeMD-160160bits20bytes
SHA-256256bits32bytes
SHA-512512bits64bytes

二、哈希算法对密码加密的实现

为什么要对密码加密储存呢?设想如果数据库中直接存入用户的密码,数据库一旦泄露,那用户的信息将暴露无遗。所以将密码加密后存入数据库,将用户密码加密后的信息与存入数据库的信息去比对验证,这样就算数据库泄露,加密后的密码并不能被直接用于登录。

1.MD5加密

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class Main {
	public static void main(String[] args) throws NoSuchAlgorithmException {
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		md5.update("XXX123456".getBytes());
		byte[] digestByte = md5.digest();
		System.out.println(Arrays.toString(digestByte));
	}
}

效果如图:
在这里插入图片描述每次加密的长度,相同内容都加密的字节数组都是相同的。
由于加密成字节数组并不方便存储,我们往往会将他转换成十六进制的字符串来代替。为了方便之后的SHA-1,SHA-256等加密的实现,我们自己创建一个HashTool工具类。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class HashTool {
	private static MessageDigest digest;
	private HashTool() {
		super();
	}
public static String digestMD5(String md5) throws NoSuchAlgorithmException {
		digest = MessageDigest.getInstance("MD5");
		digest.update(md5.getBytes());
		return byteToHex(digest.digest());
	}
public static String byteToHex(byte[] b) {
	StringBuilder sb = new StringBuilder();
	for (byte s : b) {
		String format = String.format("%02x", s);
		sb.append(format);
	}
	return sb.toString();
	}
}

本类写了一个静态的byteToHex()方法将加密的字节数组,每一位字节对应两位十六进制数(不足两位用0补充,再将MD5加密的过程封装在digestMD5()方法中,最终调用byteToHex()方法将字节数组转换成十六进制的字符串。
效果如图:
在这里插入图片描述

2.SHA-1,SHA-256,SHA-512加密

同理,这些加密只需要在MessageDigest.getInstance(加密类型)方法中填入想要加密的类型即可,我们在HashTool类中实现,代码如下

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashTool {
	private static MessageDigest digest;
	private HashTool() {
		super();
	}

public static String digestMD5(String md5) throws NoSuchAlgorithmException {
	digest = MessageDigest.getInstance("MD5");
	digest.update(md5.getBytes());
	return byteToHex(digest.digest());
	}

public static String digestSHA256(String sha256) throws NoSuchAlgorithmException {
	digest = MessageDigest.getInstance("SHA-256");
	return handler(sha256);

	}

public static String digestSHA512(String sha512) throws NoSuchAlgorithmException {
	digest = MessageDigest.getInstance("SHA-512");
	return handler(sha512);

	}

public static String digestSHA1(String sha1) throws NoSuchAlgorithmException {
	digest = MessageDigest.getInstance("SHA-1");
	return handler(sha1);

	}

private static String handler(String handle) {
	digest.update(handle.getBytes());
	return byteToHex(digest.digest());
	}

public static String byteToHex(byte[] b) {
	StringBuilder sb = new StringBuilder();
	for (byte s : b) {
		String format = String.format("%02x", s);
		sb.append(format);
		}
	return sb.toString();
	}
}

效果如图:
在这里插入图片描述(ASH-512字符串太长就不展示完全了)

3.ripeMd160加密

ripeMd160加密是第三方提供的加密包,想要使用ripeMd160加密必须导入bcprov-jdk15on-1.70.jar包。代码如下:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class BouncyDemo {
	public static void main(String[] args) throws NoSuchAlgorithmException {
		// 注册BouncyCastleProvider通知类
		Security.addProvider(new BouncyCastleProvider());
		MessageDigest ripeMd160 = MessageDigest.getInstance("RipeMD160");
		ripeMd160.update("wbjxxmy".getBytes());
		byte[] result = ripeMd160.digest();
		System.out.println("RipeMD160加密后为:" + HashTool.byteToHex(result));
		System.out.println("RipeMD160加密的字节长度为:" + ripeMd160.digest().length);
	}
}

导入jar包后,想要让java程序知道你想使用RipeMD160加密,得先使用Seurity安全工具类的addProvider()方法,new一个BouncyCastleProvider来注册BouncyCastleProvider通知类,通知java程序将可能使用bcprov-jdk15on-1.70.jar包下的算法。
RipeMD160算法加密结果如图:
在这里插入图片描述

4.加盐

以上的加密真的就安全了吗?答案是否定的,我们还要防止彩虹表攻击
彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值、微缩图、摘要、指纹、哈希密文)而准备。
所以,为了预防彩虹表攻击,我们可以加盐(salt):对每个口令额外添加一个随机数,进行组合。
digest=md5(salt+inputpassword)
经过加盐处理的数据库表如下所示:

usernamesaltpassword
张三H1r0a894152fff4f97e8fb2b8f304c5c56ebb
李四7$p2wfc195df5b3ff11af8d07e10be912fb44
王五z5Sk91c8854242ab5c4a493a808538be5baf1

还有一种类似加盐,但比加盐更安全的加密方式,详情跳转至Hmac算法


总结

本文章简单介绍了哈希算法,并且实现了基本的常用的哈希算法对密码的加密。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈希算法是一种常用的加密算法,可以将输入的任意长度的数据转化成固定长度的哈希值。在C语言中,我们可以通过一些常用的哈希算法实现来进行加密。 一个常用的哈希算法是MD5(Message Digest Algorithm 5)。在C语言中,我们可以使用openssl库中的MD5函数来实现。 首先,我们需要引入openssl头文件并链接openssl库: ``` #include <openssl/md5.h> #include <stdio.h> #include <string.h> #include <stdlib.h> ``` 接下来,我们可以定义一个函数来实现哈希算法加密功能: ``` void md5_encrypt(char* input, char* output) { unsigned char digest[MD5_DIGEST_LENGTH]; MD5((unsigned char*)input, strlen(input), digest); for(int i = 0; i < MD5_DIGEST_LENGTH; i++) { sprintf(&(output[i*2]), "%02x", (unsigned int)digest[i]); } } ``` 在这个函数中,我们首先定义了一个unsigned char类型的数组digest用于存储MD5算法的哈希值。然后,我们调用了MD5函数来对输入的input进行哈希算法的运算。最后,我们通过sprintf函数将哈希值转化为16进制的字符串并存储在output中。 我们可以在主函数中调用md5_encrypt函数,并输出结果: ``` int main() { char input[] = "Hello World"; char output[MD5_DIGEST_LENGTH*2+1]; md5_encrypt(input, output); printf("MD5 hash: %s\n", output); return 0; } ``` 运行这段代码,我们将会得到输入"Hello World"的MD5哈希值并输出。 除了MD5,C语言中还有其他的哈希算法实现,比如SHA-1(Secure Hash Algorithm 1),SHA-256等等。实现这些哈希算法的原理和步骤类似,只需要将相应的函数和头文件进行替换即可。 需要注意的是,哈希算法是一种单向加密算法,即无法通过哈希值逆向得到原始数据。因此,哈希算法主要用于验证数据的完整性和唯一性,而不是加密敏感信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值