ASCII:只支持全英文;
JBK:支持全中文。
**URL编码:**是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分。
Base64编码
Base64编码就是把任意长度的二进制数据(Byte[] 数组)变为纯文本。
实例代码:
包含编码和解码:
//从文本文件中读取一张图片的Base64编码值
List<String> lines = Files.readAllLines(Paths.get("E:\\音乐\\img\\周杰伦.txt"));//括号里的就是一组Byte[]数组
StringBuilder sb = new StringBuilder();
for(String In:lines) {
sb.append(In);
}
System.out.println(sb.length());
//Base解码
byte[] imageByteArray = Base64.getDecoder().decode(sb.toString());
Files.write(Paths.get("E:\\音乐\\img\\zhou.jpg"),imageByteArray);
由于标准的Base64编码会出现+ 、/、=。所以是不适合把Base64编码后的字符放入URL中。
// 原始字节内容
byte[] input = new byte[] { 0x01, 0x02, 0x7f, 0x00 };
// 分别使用两种方式进行编码
String b64Encode = Base64.getEncoder().encodeToString(input);
String b64UrlEncoded = Base64.getUrlEncoder().encodeToString(input);
// 结果完全一致
System.out.println(b64Encode);
System.out.println(b64UrlEncoded);
// 分别使用两种方式进行重新解码
byte[] output1 = Base64.getDecoder().decode(b64Encode);
System.out.println(Arrays.toString(output1));
byte[] output2 = Base64.getUrlDecoder().decode(b64UrlEncoded);
System.out.println(Arrays.toString(output2));
但是使用Base64编码时,它的传输效率特别低,尤其是字符越少的情况下。因为他会把原始数据长度增加1/3。
URL编码
URL的编码:
实例代码:
String content = "我本将心向明月";
String result = Base64.getEncoder().encodeToString(content.getBytes());
System.out.println(result);
URL的解码:
代码实例:
String value = "ztKxvr2r0MTP8sP31MI=";
byte[] param = Base64.getDecoder().decode(value);
System.out.println(param);
哈希算法
哈希算法又叫摘要算法。
它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法的目的:为了验证原始数据是否被篡改。
哈希算法的特点是:1、相同的输入一定得到相同的输出;
2、不同的输入 大概率得到不同的输出。
哈希碰撞
是指两个不同的输入得到了相同的输出。
"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0
"通话".hashCode(); // 0x11ff03
"重地".hashCode(); // 0x11ff03
碰撞时不能避免的,因为输出的字节长度是固定的,String和hashcode()输出的是4个字节整数,最多只有4294967296种输出,单数输入的数据长度是不固定的,有无数种输入可能。
MD5算法
Java标准库提供了常用的哈希算法,并且由一套统一的接口。
import java.security.MessageDigest;
public class main {
public static void main(String[] args) {
// 创建一个MessageDigest实例:
MessageDigest md = MessageDigest.getInstance("MD5");
// 反复调用update输入数据:
md.update("Hello".getBytes("UTF-8"));
md.update("World".getBytes("UTF-8"));
// 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
byte[] results = md.digest();
StringBuilder sb = new StringBuilder();
for(byte bite : results) {
sb.append(String.format("%02x", bite));
}
System.out.println(sb.toString());
}
}
SHA-1算法
在Java中使用SHA-1,和MD5完全一样,只需要把算法名称改为”SHA-1“。
import java.security.MessageDigest;
public class main {
public static void main(String[] args) {
// 创建一个MessageDigest实例:
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 反复调用update输入数据:
md.update("Hello".getBytes("UTF-8"));
md.update("World".getBytes("UTF-8"));
// 20 bytes: db8ac1c259eb89d4a131b253bacfca5f319d54f2
byte[] results = md.digest();
StringBuilder sb = new StringBuilder();
for(byte bite : results) {
sb.append(String.format("%02x", bite));
}
System.out.println(sb.toString());
}
}
哈希算法的用途:
1、校验下载文件
2、存储用户密码
Hmac编码
在存储用户的哈希口令时,要加盐存储,目的就在于抵御彩虹表。
而Hmac算法就是一种基于密钥的消息认证码算法,是一种更安全的信息摘要算法。
Hmac算法总是和某种哈希算法配合使用。MD5算法会“加盐”。而HmacMD5算法可以看作带有一个安全的key的MD5.
HmacMD5而不是用MD5加salt,有如下好处:
1、HmacMD5使用的key长度是64字节,更安全;
2、Hmac是标准算法,同样适用于SHA-1等其他哈希算法。
3、 Hmac输出和原有的哈希算法长度一致。
因此,HmacMD5本质上就是把key混入摘要的算法。HmacMD5中的key是Java标准库KeyGenerator生成一个随机安全的key。
代码示例:
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
public class main {
public static void main(String[] args) throws NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException, InvalidKeyException {
// 获取HmacMD5秘钥生成器
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
// 产生秘钥
SecretKey secreKey = keyGen.generateKey();
// 打印随机生成的秘钥:
byte[] keyArray = secreKey.getEncoded();
StringBuilder key = new StringBuilder();
for(byte bite:keyArray) {
key.append(String.format("%02x", bite));
}
System.out.println(key);
// 使用HmacMD5加密
Mac mac = Mac.getInstance("HmacMD5");
mac.init(secreKey); // 初始化秘钥
mac.update("HelloWorld".getBytes("UTF-8"));
byte[] resultArray = mac.doFinal();
StringBuilder result = new StringBuilder();
for(byte bite:resultArray) {
result.append(String.format("%02x", bite));
}
System.out.println(result);
}
}
和MD5相比,使用HmacMD5的步骤数是:
1、通过名称HmacMD5获取KeyGenrator对象;
2、通过KeyGenerator创建一个SecreKey实例;
3、通过名称HmacMD5获取Mac实例;
4、用SecreKey初始化Mac实例;
5、对Mac实例反复调用update(byte[])输入数据;
6、调用Mac实例的doFinal()获取最终的哈希值。
有了Hmac计算的哈希和SecreKey,但是SecreKey不能从KeyGenerstor生成,而是从一个byte[]数组恢复:
代码示例:
byte[] keyArray = {70, 31, 31, 113, -75, 45, 5, 112, -32, -32, 57, 59, -77, -52, -22, -67, -115, -15, -32, -57, 94, -78, 58, -115, 76, -104, 41, -120, -21, 28, 123, -13, -79, -17, 18, 63, -45, -14, -43, -33, -126, -115, 76, -87, -123, -16, -109, -127, -113, -114, 19, 96, 69, 73, -2, -75, -66, -88, -10, -9, -14, 104, -97, -69};
SecretKey secreKey = new SecretKeySpec(keyArray, "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(secreKey); // 初始化key
mac.update("HelloWorld".getBytes("UTF-8"));
byte[] resultArray = mac.doFinal();
StringBuilder result = new StringBuilder();
for(byte bite:resultArray) {
result.append(String.format("%02x", bite));
}
System.out.println(result);