191120_02 Java常用加密校验转换算法汇总

Java常用加密校验转换算法汇总

作者:邵发

官网:http://afanihao.cn/java

本文是Java学习指南系列教程的官方配套文档。内容介绍Java里的常用算法的使用,包含转换Hex / Base64等数据转换算法,CRC32 / MD5 / HMAC-SHA1数据签名和校验算法,DES / AES等对称加密算法。

由于篇幅的限制,本文只对各种算法的使用给出代码示例。如果对原理有不明白的地方,可以参考Java学习指南系列的《项目应用篇》,里面对每一个算法的应用背景和原理有较为详细的解释。本文附带项目源码及相关JAR包。

1.  Hex转换

在Java里,一般性的数据用byte[]表示,即字节数组。由于byte[]本身不可显示,所以为了显示和传递的方便,有时候需要把它转化为十六进制显示。

1.1 byte[] => Hex String

例如,

byte[] code   = { -5, 0, 10, 99, 20 };
String hex = Hex.encodeHexString(code, false);

code表示5个字节的数据,将其转成十六进制表字符串为:FB000A6314 。在十六进制表示下,每两个字符表示1字节的数据,即FB 00 0A 64 14共五个字节。

1.2 Hex String => byte[]

反转来,也可以

byte[] code2  = Hex.decodeHex(hex);

解码后得到长度为5字节的数组code2,和原始数据内容是一样的。

Hex是一种数据转换算法,它没有改变数据的值,仅仅是换了一个表示方式。就好比机器猫和多莱梦,说的是同一个事物。

 

2.  Base64转换

Base64,即64进制的转换。在64进制下,一共有64个基础字符。即,

'A', 'B', 'C', …, 'Y', 'Z',

'a', 'b', 'c', …, 'y', 'z',

'0', '1', '2', …, '8', '9',

'+', '-'

2.1 byte[] => Base64 String

以下示例,把4字节的数据转成Base64的表示,例如。

byte[] code   = { 12, 4 , 9, -2};
String str = Base64.encodeBase64String(code);

转换的结果为: DAQJ/g== ,虽然结果看起来有点奇怪,但这只是一个表示方式,数据的内容没有发生变化。

 

2.2 Base64 String => byte[]

反过来,也可以把Base64表示的字符串,再解码为字节数据。例如。

byte[] code2  = Base64.decodeBase64(str);

解码之后,得到的字节数组和原始内容是一致的。

 

3.  MD5校验

业界用于校验的算法有多种,比如:

Parity : 奇偶校验
ECC : 错误校验与纠正
Checksum : 和校验
CRC32 : 循环冗余校验
MD5 : 消息摘要
SHA1 : 安全哈希

其中,MD5和SHA1是Java项目里使用比较多的校验算法。

所谓校验算法,用于在传输过程中的完整性的校验。比如,A给B发送一个大文件,B在接收到之后惴惴不安,因为他不能确定这么大一个文件在传输过程中没有错误发生(比如某个字节传错了)。B怎么才能够确认这个文件的完整性呢?需采用校验算法。

MD5的基本使用公式: Code = MD5 ( Data)

其中 Data为输入的一段数据,经过MD5运算之后,得到16字节的结果,称为MD5码。

特点:
1 无论Data有多长,输出的MD5码总是16字节
2 如果Data不同,则输出的MD5码也不相同。(极大概率不同)

3.1 示例:求MD5校验码

// 待处理的数据,任意长度
byte[] data = { 12, 8, 9, -1, 87, 0, -47, 99, 14, 54 };

// 创建算法实例 ,MD5 或 SHA1
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data);
byte[] code = md.digest();

// 转成HEX显示 (参考上一章)
String result = Hex.encodeHexString(code, false);

需要注意的是,MD5算法的输出结果是一个长为16字节的byte[],通常需要转成十六进制的字符串显示。所以我们通常看到的MD5值是由32字符表示的。

 

3.2 对字符串求MD5

在Java项目中,通常需要对字符串求MD5码。示例如下。

// 待处理的字符串
String text = "阿发你好 /afanihao.cn";

// 转成字节数据
byte[] data = text.getBytes("UTF-8");

// 求消息摘要
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data);
byte[] code = md.digest();

// 转成HEX显示
String result = Hex.encodeHexString(code, false);
System.out.println("校验码: " + result);

使用MD5算法,也可以对一个很大的文件求MD5码。示例代码略。

 

4.  SHA1校验

SHA1也是一种校验算法,比MD5更强,输出20字节的校验码。它的使用方法和MD5一样,只需要把算法的名字改成SHA1就行了。

byte[] data = { 12, 8, 9, -1, 87, 0, -47, 99, 14, 54 };
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(data);
byte[] code = md.digest();
String result = Hex.encodeHexString(code, false);

 

5.  CRC32校验

CRC32也是一种校验算法,生成4字节的校验码。它在Java领域使用得不多,稍微了解一下即可。

5.1  示例:根据byte[]生成CRC32校验码

// 待处理的数据,任意长度
byte[] data = { 12, 8, 9, -1, 87, 0, -47, 99, 14, 54 };

// 创建算法实例
CRC32 crc = new CRC32();
crc.update( data );
long value = crc.getValue();

// 转成HEX显示 (参考上一章)
String result = Long.toHexString(value);
System.out.println("校验码: " + result);

 

6.  HMAC-SHA1签名

所谓签名,也是一种校验算法,只是这个校验码是无法伪造的。签名算法用于保证数据的真实现性。

例如,
    Code = HMAC-SHA1 ( Data, Key )
其中,Data为输入的数据,Key为指定的密钥。在经过HMAC-SHA1运算后,得到一个20字节的校验码。

这个校验码是无法伪造的,只有持有Key的人,才能生成相同的校验码。在传递的过程,传输双方都知晓这个密钥,才能得到相同的校验码。

6.1 示例:HMAC-SHA1签名

// 数据
byte[] data = { 12, 8, 9, -1, 87, 0, -47, 99, 14, 54 };

// 密钥
String key = "test2019";

// HMAC-SHA1 算法
Key keySpec = new SecretKeySpec(key.getBytes(), "HMACSHA1");
Mac mac = Mac.getInstance("HMACSHA1");
mac.init(keySpec);

// 更新数据
mac.update(data);

// 取得最终结果
byte[] code = mac.doFinal();
String result = Hex.encodeHexString(code, false);
System.out.println("签名: " + result);

 

6.2  HmacSha1Util 工具类

在Java项目里,常见对String的签名操作,为此封装出一个工具类HmacSha1Util。示例用法如下:

String text = "afanihao.cn | 阿发你好 | Java学习指南";
String key = "your_key_2019";
String result = HmacSha1Util(text , key);

 

7.  DES加密

下面介绍两种常见的加密算法:DES和AES。其中,DES出现的较早,而AES是它的升级替代品。

什么叫加密?加密意味着秘密,只有持有秘钥者可以解读。
(1) 加密后的数据可以解密,还原为原始数据
(2) 只有持有秘钥者可以解密

加密算法的一般公式为:
     Cipher = Encrypt( Plain, Key )
其中,Plain为原文,Key为密钥。经加密算法运算后,得到密钥。

反过来,还可以解密,公式为:
     Plain = Decrypt ( Cipher, Key)
这个加密和加密的过程是对称的(互逆的),来回使用的是同一处密钥,所以称为对称加密算法。

7.1  示例:DES加密

public static byte[] encrypt(byte[] plain, byte[] key) throws Exception
{   
    // 使用 PKCS5补齐方式
    Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");  
    SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
    c.init(Cipher.ENCRYPT_MODE, keySpec);   

    // 加密
    byte [] output = c.doFinal(plain);
    return output;
}

其中,plain为原文,key是密角,返回值为密文。

在Java项目中,密钥通常为String,需要自己转成byte[]。对于DES来说,要求密钥长度为8个字节。

7.2  示例:DES解密

public static byte[] decrypt(byte[] cipher, byte[] key) throws Exception
{   
    // 使用 PKCS5补齐方式
    Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");  
    SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
    c.init(Cipher.DECRYPT_MODE, keySpec);   

    byte [] output = c.doFinal(cipher);   
    return output;
}

同样地,在实际项目中处理的往往是String,而结果也往往要转成HEX形式表示。所以要自己添加额外的处理,自己要稍微封装一下再使用。

 

8.  AES加密

AES是用于取代DES的更高级更强的加密算法,但用法基本是类同的。AES加密密钥长度为16字节,每16字节一组进行加密。

8.1  示例:AES加密

public static byte[] encrypt(byte[] plain, byte[] key) throws Exception
{
	// AES
	Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
	SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
	c.init(Cipher.ENCRYPT_MODE, keySpec);

	// 加密
	byte[] output = c.doFinal(plain);
	return output;
}

 

8.2 示例:AES解密

public static byte[] decrypt(byte[] cipher, byte[] key) throws Exception
{
	// AES
	Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
	SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
	c.init(Cipher.DECRYPT_MODE, keySpec);

	byte[] output = c.doFinal(cipher);
	return output;
}

其中,在准备密钥的时候,需保证密钥长度不少于16字节。

 

8.3 AESUtil工具类

由于在Java项目中要处理的信息一般是String,所以对上述AES算法做一个简单的封装,得到AESUtil工具类。

示例用法如下:

String key = "your_key_2910";
String plain = "阿发你好 | afanihao.cn | Java学习指南系列教程 ";
String cipher = AESUtil.encrypt(plain, key); // 加密
String plain2 = AESUtil.decrypt(cipher, key); // 解密

这样在项目中调用就非常的简单了,只需要自己指定一下密钥,就可以进行加密解密了。

 

以上介绍了几种常见算法的使用,如果有对应用背景、原理和项目使用不太清楚的地方,可以参考Java学习指南系列教程的《项目应用篇》。 本篇演示所用的项目源码和JAR包在此处可以获取

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿发你好

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

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

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

打赏作者

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

抵扣说明:

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

余额充值