目录
常用加密算法对比
加密算法 | 描述 |
---|---|
SHA | 安全散列算法。单向加密、数据不可逆(即不可恢复)。长度是固定的。 |
BASE64 | 1、BASE64 有自己的编码表,可编码,也可解码;解码后能得到源内容。 2、BASE64 编码的长度是不固定的,随着源字符串的增加而增加。 3、在某些不方便使用中文的地方,可以通过 BASE64 编码成可见字符,需要中文时再解码回来即可,比如 url 地址,或者 Cookie. |
MD5 | 信息摘要是安全的单向哈希函数,对大小的信息输出固定长度的哈希值,单向加密、数据不可逆。 摘要好比指纹,每个人都是唯一的,相同的源数据,摘要也一样,不同的数据,摘要则不一样。摘要只是源数据的局部,所以想要解码回去恢复整个源数据是不行的,因为是不完整的。 |
DES | Data Encrytion Standard(数据加密标准) , 特点:1. 对称加密 2. 同一个 SECRET_KEY(密钥) |
AES | Advanced Encrytion Standard(高级加密标准),特点:1. 对称加密 2. 一个 SECRET_KEY(密钥)扩展成多个子 SK,轮加密 |
RSA | 1. 非对称加密,即:PK(PUBLIC_KEY 公钥) 与 SK( SECRET_KEY 密钥) 不是同一个 2. PK 加密时,必须用 SK 解密、反之 SK 加密时,必须用 PK 解密, 3. PK 决定 SK,但是 PK 很难算出 SK(数学原理:两个大质数相乘,积很难因式分解) 4. 速度慢,适合对少量数据加密 |
SM2 | 国密算法,非对称算法,需要公钥和私钥,用来替换 RSA |
SM3 | 国密算法,摘要/杂凑算法,用来替换MD5、SHA-1、SHA-2 |
SM4 | 国密算法,对称算法,分组密码算法,用于替代DES/AES等国际算法 |
Base64 编解码
1、BASE64 有自己的编码表,可编码,也可解码;解码后能得到源内容。
2、BASE64 编码的长度是不固定的,随着源字符串的增加而增加。
3、比如登陆的密码单纯只用 BASE64 编码的话,是可以再解密复原的,但是用了 MD5 摘要之后则不能再复原了。
4、在某些不方便使用中文的地方,可以通过 BASE64 编码成可见字符,需要中文时再解码回来即可,如 Cookie 中是不能存储中文的。
5、BASE64Encoder 用于编码、BASE64Decoder 用于解码,都位于 sun.misc 包下。
6、Base64 编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。为了保证所输出的编码为可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | i | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
/**
* BASE64 编码
* BASE64 有自己的编码表,可编码,同时可解解码;长度是不固定的,随着源字符串的增加而增加
* 1、比如登陆的密码单纯只有 BASE64 转码的话,是可以再解密的,但是用了 MD5 摘要之后则不能再返回了,
* 2、在某些不方便使用中文的地方,可以通过 BASE64 转码成可见字符,需要中文时再解码回来即可,如 Cookie 中是不能存储中文的
*
* @param message 待编码的源数据
* @return BASE64 编码后的字符串.
*/
public static String base64Encode(String message) {
String result = "";
try {
if (message == null || "".equals(message.trim())) {
return result;
}
result = base64Encode(message.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
/**
* BASE64Encoder 编码,重载方法.
*
* @param message
* @return
*/
public static String base64Encode(byte[] message) {
String result = "";
if (message == null || message.length <= 0) {
return result;
}
/** BASE64Encoder 用于编码、BASE64Decoder 用于解码*/
BASE64Encoder base64Encoder = new BASE64Encoder();
result = base64Encoder.encode(message);
return result;
}
/**
* BASE64 解码
* 1、BASE64 有自己的编码表,可编码,同时可解密;长度是不固定的,随着源字符串的增加而增加
* 2、比如登陆的密码单纯只有 BASE64 的转码的话,是可以再解密返回的,但是用了 MD5 摘要之后则不能再返回了,
* 3、在不方便使用中文的地方,可以通过 BASE64 转码成可见字符,需要中文时再解码回来即可,如 Cookie 中是不能存储中文的
*
* @param message 待解码的字符串,如果为空,则返回空字符串.
* @return
*/
public static String base64Decode(String message) {
String result = "";
try {
if (message == null || "".equals(message.trim())) {
return result;
}
/** BASE64Encoder 用于编码、BASE64Decoder 用于解码*/
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] decoderByte = base64Decoder.decodeBuffer(message);
result = new String(decoderByte, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String sourceMessage = "123456万里长城_&*$#.Nice";
String encodeMsg = base64Encode(sourceMessage);
String decodeMsg = base64Decode(encodeMsg);
System.out.println("原字符:" + sourceMessage);//原字符:123456万里长城_&*$#.Nice
System.out.println("base64 编码后:" + encodeMsg);//base64 编码后:MTIzNDU25LiH6YeM6ZW/5Z+OXyYqJCMuTmljZQ==
System.out.println("base64 解码后:" + decodeMsg);//base64 解码后(可以解码):123456万里长城_&*$#.Nice
}
src/main/java/com/wmx/thymeleafapp/utils/Base64Utils.java · 汪少棠/thymeleafapp - Gitee.com
MessageDigest 信息摘要
1、java.security.MessageDigest 类为应用程序提供信息摘要算法,如 SHA-1、SHA-256、MD5。
2、信息摘要是安全的单向哈希函数,其信息大小是任意的,且输出为固定长度的哈希值,所以通常会结合 BAse64 编码一起使用,将哈希值转换为可视字符。如果直接使用 new String(byte[] bytes) 是会乱码的
3、摘要好比指纹,每个人都是唯一的,相同的源数据,摘要也一样,不同的数据,摘要则不一样。摘要只是源数据的局部,所以想要解码回去恢复整个源数据是不行的,因为是不完整的。
方法 | 描述 |
---|---|
MessageDigest getInstance(String algorithm) | 返回实现指定摘要算法的 MessageDigest 对象。如 SHA-1、SHA-256、MD5 |
update(byte[] input) | 使用指定的字节数组更新摘要。 |
update(byte[] input, int offset, int len) | 从指定的偏移量开始,使用指定的字节数组更新摘要。 |
byte[] digest() | 通过执行最后的操作(如填充)来完成哈希计算,进行此调用后,将重置摘要。 |
byte[] digest(byte[] input) | 使用指定的字节数组对摘要执行最终更新,然后完成摘要计算。相当于先调用 update(byte[] input),然后调用 digest()。 |
boolean isEqual(byte[] digesta, byte[] digestb) | 比较两个摘要是否相等。进行简单的字节比较。如果摘要相等,则返回true,否则返回false。 |
reset() | 重置摘要以供进一步使用。 |
String getAlgorithm() | 返回算法名称 |
int getDigestLength() | 返回摘要的长度(字节),就是 digest() 方法返回的字节数组的长度. |
/**
* 将任意字符通过 MD5 摘要 与 Base64 进行定长加密
*
* @param message 待加密字符
* @param algorithm 信息生成摘要的算法,默认为 md5,可选值有 SHA-1、SHA-256、MD5
* @return 加密后字符
*/
public static String digestEncryption(String message, String algorithm) {
String result = "";
try {
algorithm = algorithm == null ? "MD5" : algorithm;
//指定信息摘要算法提取摘要的哈希值. 哈希值字节数组,如果直接 new String(md5Byte) 是会乱码的
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
byte[] md5Byte = messageDigest.digest(message.getBytes());
//使用 BASE64 进行定长编码
BASE64Encoder base64Encoder = new BASE64Encoder();
result = base64Encoder.encode(md5Byte);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String sourceMessage = "123456万里长城_&*$#.Nice";
System.out.println("原字符:" + sourceMessage);//原字符:123456万里长城_&*$#.Nice
String md5Msg = digestEncryption(sourceMessage, "md5");
String sha1Msg = digestEncryption(sourceMessage, "SHA-1");
String sha256Msg = digestEncryption(sourceMessage, "SHA-256");
//md5 + base64 加密后:rIJQEL19bo+eV5p7qPLlDg==
System.out.println("md5 + base64 加密后:" + md5Msg);
//md5 + base64 加密后:UYg5qBdsuCdloFP+0CVPasziIEU=
System.out.println("SHA-1 + base64 加密后:" + sha1Msg);
//md5 + base64 加密后:dqTa6BTTvZ4zLF5WNAH5Cv660RxYMEIJlBRIGKdNXmM=
System.out.println("SHA-256 + base64 加密后:" + sha256Msg);
}
src/main/java/com/wmx/thymeleafapp/utils/Md5EncodeUtils.java · 汪少棠/thymeleafapp - Gitee.com
4、除了上面使用 BASE64 将生成的摘要字节数组转换成可视字符串外,也可以使用将10进制字节数组转成 16 进制字符串的方式:16 进制转换在线源码:main/java/com/wmx/thymeleafapp/utils/DataTypeConvertUtils.java
MD5 信息摘要算法
1、压缩性:任意长度的数据,计算出来的 MD5 值都是固定的
2、容易计算: 从原数据计算出 MD5 值是非常方便的
3、抗修改性: 对原数据做任何改动,哪怕之修改1个字节,MD5 值都有很大区别
4、强抗碰撞: 已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(伪造数据)是非常困难的。
5、应用场景:文件一致性较验、数据签名、安全访问认证 等。
提取文件摘要
1、使用实例代码参考上面的 "MessageDigest 信息摘要",下面演示对文件提取摘要:
Md5、SHA-1、SHA-256 摘要算法使用都是同理,都是通过 MessageDigest.getInstance(String algorithm) 指定.
/**
* 对文件提取摘要。
* 应用场景:文件一致性较验
* 即使是大文件也没有任何问题,因为并非一次性读取整个文件的内容到内存,而是边读边更新摘要。
*
* @param file :待提取摘要的文件
* @return
*/
public static String fileDigestV2(File file) throws Exception {
// 先检查文件是否存在
if (file == null || !file.exists() || !file.isFile()) {
return ""; // 先检查文件是否存在
}
try (InputStream inputStream = new FileInputStream(file)) {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[8192];
int bytesRead;
// 读取文件内容并更新消息摘要
while ((bytesRead = inputStream.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
// 获取MD5摘要字节数组
byte[] md5Bytes = md.digest();
// 将字节数组转换为十六进制字符串
StringBuilder sb = new StringBuilder();
for (byte b : md5Bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
src/main/java/com/wmx/thymeleafapp/utils/Md5EncodeUtils.java · 汪少棠/thymeleafapp - Gitee.com
验证很简单,随便去 Apache 上下载一个资源,比如:Commons IO – Download Apache Commons IO
然后使用代码对它进行提取摘要,最后和 apache 提供的进行对比即可。
高级重复文件检测工具类
1、特性:多级校验(大小+采样哈希+全量哈希)、并行计算、无效文件过滤。
原生 AES、DES、RSA 加解密
src/main/java/com/wmx/thymeleafapp/utils/AesUtil.java · 汪少棠/thymeleafapp - Gitee.com。
src/main/java/com/wmx/thymeleafapp/utils/DesUtil.java · 汪少棠/thymeleafapp - Gitee.com。
src/main/java/com/wmx/thymeleafapp/utils/ReaUtil.java · 汪少棠/thymeleafapp - Gitee.com。
国密算法加密、解密:SM2、SM3、SM4
https://blog.csdn.net/wangmx1993328/article/details/108888130。