Java中的编码算法与常用的加密算法

URL编码算法

        URL编码的出现是出于兼容性的考虑,由于很多 服务器只识别ASCII字符,当包含中文这种非ASCII码时,如果字符是 A ~ Z , a ~ z , 0 ~ 9 以及 - 、 _ 、 . 、 * ,则保持不变; 如果是其他字符,先转换为 UTF-8 编码,然后对每个字节以 %XX 表示。

以下是基于URL编码算法的编码与解码,需要注意的是编码与解码时字符编码集应当设置为UTF-8


public class Demo01 {public static void main(String[] args) throws UnsupportedEncodingException {//编码String url = "https://www.baidu.com/s";String result = "语雀";String encode = URLEncoder.encode(result, "utf-8");System.out.println(encode);System.out.println(url+"?wd="+encode);//解码String param = "https://www.baidu.com/s?wd=%E6%88%91%E6%9C%AC%E5%B0%86%E5%BF%83%E5%90%91%E6%98%8E%E6%9C%88";String content = URLDecoder.decode(param, "utf-8");System.out.println(content);}
}

BASE64编码算法

Base64 编码可以把任意长度的二进制数据变为纯文本(在java中二进制数据为byte数组),并且纯文本内容中且只包含指定字符内 容: A ~ Z 、 a ~ z 、 0 ~ 9 、 + 、 / 、 = 。它的原理是把 3 字节的二进制数据按 6bit 一组,用 4 个int整数表示,然后查表, 把 int 整数用索引对应到字符,得到编码后的字符串。 6 位整数的范围总是 0 ~ 63 ,所以,能用 64 个字符表示:字符 A ~ Z 对应索引 0 ~ 25 ,字符 a ~ z 对应索引 26 ~ 51 ,字符 0 ~ 9 对应索引 52 ~ 61 ,最后两个索引 62 、 63 分别用字符 + 和 / 表示。

以下是基于BASE64编码算法的编码与解码

public class Demo02 {public static void main(String[] args) throws IOException {byte[] imagebyteArray = Files.readAllBytes(Paths.get("D:\\tupian11\\douban\\珠峰队长.jpg"));//读取本地图片并且保存在byte数组里String imageData= Base64.getEncoder().encodeToString(imagebyteArray);//将图片以BASE64编码方式进行编码byte[] imageResultArray = Base64.getDecoder().decode(imageData);//将图片以BASE64编码方式进行解码Files.write(Paths.get("D:\\tupian12\\你的队长.jpg"),imageResultArray);//将解码得到的保存在byte字节数组,并且写入指定目录}
}

小结

URL 编码和 Base64 编码都是编码算法,它们不是加密算法; URL 编码的目的是把任意文本数据编码为 % 前缀表示的文本,便于浏览器和服务器处理; Base64 编码的目的是把任意二进制数据编码为文本,但编码后数据量会增加 1/3 。

哈希算法(加密)

        什么是哈希算法呢?好像熟悉又陌生

        哈希算法( Hash )又称摘要算法( Digest ),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。哈希算 法的目的:为了验证原始数据是否被篡改。

而哈希算法的特点在于: 相同的输入一定得到相同的输出; 不同的输入大概率得到不同的输出。

我们可以知道 :根据碰撞概率,哈希算法的输出长度越长,就越难产生碰撞,也就越安全。

常用的Hash算法
算法输出长度(位)输出长度(字节)
MD5128 bits16 bytes
SHA-1160 bits20 bytes
RipeMD-160160 bits20 bytes
SHA-256256 bits32 bytes
SHA-512512 bits64 bytes

MD5算法:

在使用 MessageDigest 时,我们首先根据哈希算法获取一个 MessageDigest 实例,然后,反复调用 update(byte[]) 输入数据。当输入结束后,调用 digest() 方法获得 byte[] 数组表示的摘要,最后,把它转换为十六进制的字符串。以下代码我们以MD5算法为例。

public class Demo06 {public static void main(String[] args) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update("天青色等烟雨".getBytes());md5.update("而我在等你".getBytes());byte[] resultArray=md5.digest();System.out.println(Arrays.toString(resultArray));md5.update("天青色等烟雨而我在等你".getBytes());byte[] resltArray2=md5.digest();System.out.println(Arrays.toString(resltArray2));} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

SHA-1算法:

SHA-1 也是一种哈希算法,它的输出是 160 bits ,即 20 字节。 SHA-1 是由美国国家安全局开发的, SHA 算法实际上是一个系列,包括 SHA-0 (已废弃)、 SHA-1 、 SHA-256 、 SHA-512 等。 在 Java 中使用 SHA-1 ,和 MD5 完全一样,只需要把算法名称改为" SHA-1 ":

public class main {public static void main(String[] args) {// 创建一个MessageDigest实例:MessageDigest md = MessageDigest.getInstance("SHA-1");// 反复调用update输入数据:md.update("天青色等烟雨".getBytes("UTF-8"));md.update("而我在等你".getBytes("UTF-8"));// 20 bytes: db8ac1c259eb89d4a131b253bacfca5f319d54f2byte[] results = md.digest();StringBuilder sb = new StringBuilder();for(byte bite : results) {sb.append(String.format("%02x", bite));}System.out.println(sb.toString());}}

Hmac加密算法

        Hmac 算法就是一种基于密钥的消息认证码算法,它的全称是 Hash-based Message Authentication Code ,是一种更安全的消息 摘要算法。

Hmac 算法总是和某种哈希算法配合起来用的

例如,我们使用 MD5 算法,对应的就是 Hmac MD5 算法,它相当于“加盐” 的 MD5 : HmacMD5 ≈ md5(secure_random_key, input)

因此, HmacMD5 可以看作带有一个安全的 key 的 MD5 。使用 HmacMD5 而不是用 MD5 加 salt ,有如下好处:

HmacMD5 使用的 key 长度是 64 字节,更安全;

Hmac 是标准算法,同样适用于 SHA-1 等其他哈希算法;

Hmac 输出和原有的哈希算法长度一致。

可见, Hmac 本质上就是把 key 混入摘要的算法。

验证此哈希时,除了原始的输入数据,还要提供 key 。

为了保证安全,我们不会自 己指定 key ,而是通过 Java 标准库的 KeyGenerator 生成一个安全的随机的 key 。

public class Demo10 {public static void main(String[] args) {String str = "mlmdxbldm";try {KeyGenerator kg = KeyGenerator.getInstance("HmacMD5");SecretKey key = kg.generateKey();byte[] keyByteArray = key.getEncoded();StringBuilder sb = new StringBuilder();for(byte b : keyByteArray) {sb.append(String.format("%02X", b));}System.out.println(Arrays.toString(keyByteArray));System.out.println("密钥为"+sb);System.out.println("密钥长度为"+keyByteArray.length);System.out.println("密钥字节数为"+sb.length());//使用秘钥Mac mac = Mac.getInstance("HmacMD5");//初始化mac.init(key);//加密mac.update(str.getBytes());//byte[] result = mac.doFinal();StringBuilder sb1 = new StringBuilder();for(byte b : result) {sb1.append(String.format("%02X", b));}System.out.println("加密结果"+sb1);System.out.println("加密结果长度"+sb1.length());} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvalidKeyException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

和 MD5 相比,使用 HmacMD5 的步骤是:

1. 通过名称 HmacMD5 获取 KeyGenerator 实例;

2. 通过 KeyGenerator 创建一个 SecretKey 实例;

3. 通过名称 HmacMD5 获取 Mac 实例;

4. 用 SecretKey 初始化Mac实例;

5. 对 Mac 实例反复调用 update(byte[]) 输入数据;

6. 调用 Mac 实例的 doFinal() 获取最终的哈希值。

如果我们想恢复并且验证,其中new SecretKetSpec则是恢复密钥时传入数组的代码。

package com.my.hyz.homework;import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;public class Demo11 {public static void main(String[] args) {String str = "mlmdxbldm";try {byte[] keyByteArray = {78, -100, -109, 29, 87, -46, -77, -36, 2, -2, -103,             -22, 45, -97, -70, 60, 102, 120, -21, 0, 79, 97, 111,23, 38, 39, -110, 7, 102, 6, -101, 105, -6, -87, 114, 
21, -82, 10, -119, -81, -57, 95, 95, -7, -97, -87, 79,-25, -87, -63, 65, -127, -90, -85, 75, 37, -36, -107,114, 64, 40, 111, -86, -24};SecretKey key = new SecretKeySpec(keyByteArray, "HmacMD5");Mac mac = Mac.getInstance("HmacMD5");//初始化mac.init(key);//加密mac.update(str.getBytes());//byte[] result = mac.doFinal();StringBuilder sb1 = new StringBuilder();for(byte b : result) {sb1.append(String.format("%02X", b));}System.out.println("加密结果"+sb1);} catch (InvalidKeyException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部