这是我参与更文挑战的第9天,活动详情查看: 更文挑战。终于第九天了,达到了这次活动的第一个节点,存货用的差不多了,要开始动手肝了,是时候展现真实的实力了。
专栏内上一篇文章有讲到常见的加密算法,包括
非对称加密
、对称加密
、以及特殊的加密Hash摘要
。这篇文章是实践篇,来讲如何用Java
开发语言实现Hash
,具体实现的有MD5(Message Digest version 5)和SHA(Secure Hash Algorithm)。
一、回顾
在动手之前,先来回顾一下什么是Hash摘要
。
Hash摘要
也被称为加密散列函数,它以任意大小的数据作为输入(消息)并产生固定长度的散列值。
Hash摘要
最重要的特性之一是,生成具有给定散列(安全单向)的消息,并且是不可逆的。Hash摘要
经常用于检查数据完整性,例如根据其已知的散列值检查下载文件的完整性;还有一个更为见的用法是在数据库中加密用户的密码。
二、实践步骤
Java
语言给我们提供了丰富的类库,其中MessageDigest
类能帮助我们实现MD5
,HASH
算法。
生成Hash
的步骤分为两种情况。
2.1 内容较少
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] inputBytes = ${dynamic message} // 待加密的内容
byte[] hashBytes = digest.digest(inputBytes);
2.2 内容较多(文件)
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] inputBytes = ${dynamic message}// 待加密的内容
digest.update(inputBytes);
byte[] hashedBytes = digest.digest();
三、例子
Hash摘要
工具类如下:
public interface DigestUtils {
static String SHA256(byte[] bytes) throws NoSuchAlgorithmException {
return digest(bytes, AlgorithmType.SHA256);
}
static String SHA512(byte[] bytes) throws NoSuchAlgorithmException {
return digest(bytes, AlgorithmType.SHA512);
}
static String MD5(byte[] bytes) throws NoSuchAlgorithmException {
return digest(bytes, AlgorithmType.MD5);
}
static String SHA1(byte[] bytes) throws NoSuchAlgorithmException {
return digest(bytes, AlgorithmType.SHA1);
}
/**
* 将待加密的内容和算法名称作为输入,并返回计算出的哈希值的十六进制形式
* @param aByte 待加密的内容
* @param algorithm 算法名称
* @return 哈希值的十六进制形式
* @throws NoSuchAlgorithmException 没有找到加密算法异常
*/
static String digest(byte[] aByte, @NotNull String algorithm) throws NoSuchAlgorithmException {
final MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
final byte[] digest = messageDigest.digest(aByte);
return ArraysStringConverter.convertByteArrayToHexString(digest);
}
interface AlgorithmType {
String SHA1 = "SHA-1";
String MD5 = "MD5";
String SHA256 = "SHA-256";
String SHA512 = "SHA-512";
}
}
在工具内有用到将字节数组转成十六进制的字符串的方法,具体实现如下
public interface ArraysStringConverter {
/**
* 转换字节数组到16进制的字符串
*
* @param arrayBytes 字节数组
* @return 16进制的字符串
*/
static String convertByteArrayToHexString(byte[] arrayBytes) {
StringBuilder stringBuffer = new StringBuilder();
for (byte arrayByte : arrayBytes) {
stringBuffer.append(Integer.toString((arrayByte & 0xff) + 0x100, 16)
.substring(1));
}
return stringBuffer.toString();
}
}
Main
函数测试方法就不列举出来,已经在生产环境中使用了。Hash
一个文件的代码就不给出来,无法就是把文件的按照指定的长度读出来,不断进行digest.update()
,参照实践步骤的内容较多(文件)的步骤进行即可。
四、源码地址
附上Github
的源代码地址
training.platform.training.java.crypto.digest