安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
目前SHA有五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美国安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布,也是美国的政府标准,后四者有时并称为SHA-2。
SHA家族各个参数对比如下:
/ | SHA-1 | SHA-224 | SHA-256 | SHA-SHA-384 | SHA-512 |
---|---|---|---|---|---|
消息摘要长度 | 160 | 224 | 256 | 384 | 512 |
消息长度 | 2 64 2^{64} 264 | 2 64 2^{64} 264 | 2 64 2^{64} 264 | 2 128 2^{128} 2128 | 2 128 2^{128} 2128 |
字长度 | 32 | 32 | 32 | 64 | 64 |
分组长度 | 512 | 512 | 512 | 1024 | 1024 |
步骤数 | 80 | 64 | 64 | 80 | 80 |
工作中经常用的SHA的加密方法,比如SHA-1、SHA-224、SHA-256、SHA-384,SHA-512,总是分不清楚,让自己疑惑:是不是要写几个不同的工具类去实现?来,我告诉你!一个就够了,用Java原生摘要实现SHA的加密。
ShaUtil .java
package com.alian.csdn.utils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @program: CSDN
* @description: SHA工具类
* @author: Alian
* @create: 2021-06-01 15:20:10
**/
public class ShaUtil {
private static final String SHA_1 = "SHA-1";
private static final String SHA_224 = "SHA-224";
private static final String SHA_256 = "SHA-256";
private static final String SHA_384 = "SHA-384";
private static final String SHA_512 = "SHA-512";
private static final char[] hexDigits = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String getSHA1(String painText, boolean uppercase) {
return getSha(painText, SHA_1, uppercase);
}
public static String getSHA224(String painText, boolean uppercase) {
return getSha(painText, SHA_224, uppercase);
}
public static String getSHA256(String painText, boolean uppercase) {
return getSha(painText, SHA_256, uppercase);
}
public static String getSHA384(String painText, boolean uppercase) {
return getSha(painText, SHA_384, uppercase);
}
public static String getSHA512(String painText, boolean uppercase) {
return getSha(painText, SHA_512, uppercase);
}
/**
* 利用Java原生摘要实现SHA加密(支持大小写,默认小写)
*
* @param plainText 要加密的数据
* @param algorithm 要使用的算法(SHA-1,SHA-2224,SHA-256,SHA-384,SHA-512)
* @param uppercase 是否转为大写
* @return
*/
private static String getSha(String plainText, String algorithm, boolean uppercase) {
//输入的字符串转换成字节数组
byte[] bytes = plainText.getBytes(StandardCharsets.UTF_8);
MessageDigest messageDigest;
try {
//获得SHA转换器
messageDigest = MessageDigest.getInstance(algorithm);
//bytes是输入字符串转换得到的字节数组
messageDigest.update(bytes);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA签名过程中出现错误,算法异常");
}
//转换并返回结果,也是字节数组,包含16个元素
byte[] digest = messageDigest.digest();
//字符数组转换成字符串返回
String result = byteArrayToHexString(digest);
//转换大写
return uppercase ? result.toUpperCase() : result;
}
/**
* 将字节数组转为16进制字符串
*
* @param bytes 要转换的字节数组
* @return
*/
private static String byteArrayToHexString(byte[] bytes) {
StringBuilder builder = new StringBuilder();
for (byte b : bytes) {
//java.lang.Integer.toHexString() 方法的参数是int(32位)类型,
//如果输入一个byte(8位)类型的数字,这个方法会把这个数字的高24为也看作有效位,就会出现错误
//如果使用& 0XFF操作,可以把高24位置0以避免这样错误
String temp = Integer.toHexString(b & 0xFF);
if (temp.length() == 1) {
//1得到一位的进行补0操作
builder.append("0");
}
builder.append(temp);
}
return builder.toString();
}
}
接下里我们对ShaUtil工具类进行一些测试,代码如下:
/**
* SHA计算(SHA-1,SHA-2224,SHA-256,SHA-384,SHA-512)
* 此处单元测试的注解是采用:org.junit.Test
*/
@Test
public void sha() {
String plainText="Alian";
System.out.println("-----------------------------------SHA1-------------------------------------------------");
System.out.println("小写的SHA1加密结果:"+ShaUtil.getSHA1(plainText,false));
System.out.println("大写的SHA1加密结果:"+ShaUtil.getSHA1(plainText,true));
System.out.println("-----------------------------------SHA224-----------------------------------------------");
System.out.println("小写的SHA224加密结果:"+ShaUtil.getSHA224(plainText,false));
System.out.println("大写的SHA224加密结果:"+ShaUtil.getSHA224(plainText,true));
System.out.println("-----------------------------------SHA256-----------------------------------------------");
System.out.println("小写的SHA256加密结果:"+ShaUtil.getSHA256(plainText,false));
System.out.println("大写的SHA256加密结果:"+ShaUtil.getSHA256(plainText,true));
System.out.println("-----------------------------------SHA384-----------------------------------------------");
System.out.println("小写的SHA384加密结果:"+ShaUtil.getSHA384(plainText,false));
System.out.println("大写的SHA384加密结果:"+ShaUtil.getSHA384(plainText,true));
System.out.println("-----------------------------------SHA512-----------------------------------------------");
System.out.println("小写的SHA512加密结果:"+ShaUtil.getSHA512(plainText,false));
System.out.println("大写的SHA512加密结果:"+ShaUtil.getSHA512(plainText,true));
}
运行结果:
-----------------------------------SHA1-------------------------------------------------
小写的SHA1加密结果:58800795a56cf404b5f67173c20dbc0a3eace5a6
大写的SHA1加密结果:58800795A56CF404B5F67173C20DBC0A3EACE5A6
-----------------------------------SHA224-----------------------------------------------
小写的SHA224加密结果:c2dc46888be174c2599aabd58e78177f3d2f4a795a7724fbed0b78f1
大写的SHA224加密结果:C2DC46888BE174C2599AABD58E78177F3D2F4A795A7724FBED0B78F1
-----------------------------------SHA256-----------------------------------------------
小写的SHA256加密结果:8c9781ffb256b431a5e38b9f7bd81df0c4bcbd0f835feb31126c4f5a7f4bb5e2
大写的SHA256加密结果:8C9781FFB256B431A5E38B9F7BD81DF0C4BCBD0F835FEB31126C4F5A7F4BB5E2
-----------------------------------SHA384-----------------------------------------------
小写的SHA384加密结果:9fbdf2441015cf0c8e49a49b3ce88fc0d508e33f8313dfa452239b4062b45a07df9938ebac3c7198353cf3aad18ae655
大写的SHA384加密结果:9FBDF2441015CF0C8E49A49B3CE88FC0D508E33F8313DFA452239B4062B45A07DF9938EBAC3C7198353CF3AAD18AE655
-----------------------------------SHA512-----------------------------------------------
小写的SHA512加密结果:2daf6197b540d862ce2c73edb14e3ff9e743724e3b96592a4cd71797ffe045b5a5d89865632e86ed338f2c534b4f698818fa670b7eae28dc493d1e1f4a455c89
大写的SHA512加密结果:2DAF6197B540D862CE2C73EDB14E3FF9E743724E3B96592A4CD71797FFE045B5A5D89865632E86ED338F2C534B4F698818FA670B7EAE28DC493D1E1F4A455C89
以上就是今天要讲的内容,本文简单介绍了SHA,并编写了一个SHA工具类,有兴趣的同学可以去了解一下SHA算法的原理,因为安全性问题,平常的工作中尽量不使用SHA-1,改为SHA-256或者SHA-512或者采用其他安全性高的算法。如果觉得对你有帮助,欢迎大家评论交流。