On several common encryption algorithm

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_34845394/article/details/102759238


All of the following code is based on jdk8

All Apache-based implementation will need to introduce the following package:

<!-- apache.codec:编码方法的工具类包 -->
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

A coding format (Logically speaking this is not really encrypted, but more commonly used)

Encoding format algorithm

Second, the message digest algorithm (Logically speaking this is not really encrypted, but more commonly used)

Message-Digest Algorithm

Based on the above 编码格式算法and 消息摘要算法wrote a basic encryption tools, 对称加密and 非对称加密there are separate tools, look down to know.

package com.blog.www.util.coder.base;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.springframework.util.Base64Utils;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.Random;

/**
 * 基础编码工具类
 * <br/>
 * 包含以下几种加密:
 * <ul>
 *     <li>Base64</li>
 *     <li>URLEncoder、URLDecoder</li>
 *     <li>MD5</li>
 *     <li>MD5加随机盐</li>
 *     <li>SHA</li>
 *     <li>MAC</li>
 * </ul>
 * <p>
 * 注意: <br>
 * Base64加密可逆,一般用来编码信息发送,甚至可以把图片转换成字符串发送到前端显示。注意不要用来发送机密信息! <br>
 * MD5、SHA、MAC这三种加密算法,是不可逆加密,我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。
 * <p>
 * 创建人:leigq <br>
 * 创建时间:2017年10月23日 下午10:39:06 <br>
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BaseCoderUtils {
	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ BASE64 编码、解码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */

	/**
	 * BASE64加密
	 * <br/>
	 *
	 * @param binaryData 待加密二进制数据
	 * @return 加密后字符串
	 */
	public static String encryptBase64(final byte[] binaryData) {
		// 安卓自带实现,因为安卓用不了Apache的实现,所以只能用自带的实现。注意,Base64.CRLF才对应Apache的默认模式!
		// return Base64.encodeToString(key, Base64.CRLF);
		return Base64Utils.encodeToString(binaryData);
	}

	/**
	 * BASE64解密
	 * <br/>
	 *
	 * @param base64String 加密后字符串
	 * @return 原始二进制数据
	 */
	public static byte[] decryptBase64(final String base64String) {
		// 安卓自带实现
		// return Base64.decode(key, Base64.CRLF);
		return Base64Utils.decodeFromString(base64String);
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ BASE64 编码、解码 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */






	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ URL 编码、解码  ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */

	/**
	 * 将 URL 编码
	 */
	public static String encodeURL(final String data) {
		String target;
		try {
			target = URLEncoder.encode(data, StandardCharsets.UTF_8.name());
		} catch (Exception e) {
			log.error("编码出错!", e);
			throw new RuntimeException(e);
		}
		return target;
	}

	/**
	 * 将 URL 解码
	 */
	public static String decodeURL(final String data) {
		String target;
		try {
			target = URLDecoder.decode(data, StandardCharsets.UTF_8.name());
		} catch (Exception e) {
			log.error("解码出错!", e);
			throw new RuntimeException(e);
		}
		return target;
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ URL 编码、解码  ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */







	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MD5加密相关  ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */

	/**
	 * MD5加密
	 *
	 * @param data
	 * @return 大写
	 */
	public static String encryptMD5(final byte[] data) {
		return DigestUtils.md5Hex(data).toUpperCase();
	}

	/**
	 * MD5加密,字符串到字符串
	 *
	 * @param data
	 * @return 大写
	 */
	public static String encryptMD5(final String data) {
		return encryptMD5(data.getBytes());
	}

	/**
	 * 3次MD5加密,字符串到字符串
	 *
	 * @param data
	 * @return 大写
	 */
	public static String encryptTriMD5(final String data) {
		int count = 3;
		String md5 = data;
		for (int i = 0; i < count; i++) {
			md5 = encryptMD5(md5);
		}
		return md5;
	}

	/**
	 * 生成含有随机盐的加密字符串
	 *
	 * @param data 待加密的字符
	 * @return 加密后的字符(含 16 位随机盐),大写
	 */
	public static String encryptMD5WithRandomSalt(final String data) {
		return encryptMd5WithRandomSalt(data);
	}

	/**
	 * 校验密码是否正确
	 *
	 * @param data              待验证的字符(明文)
	 * @param md5StringWithSalt 加密后的字符(含 16 位随机盐)
	 * @return 验证结果
	 */
	public static boolean verifyMD5WithRandomSalt(final String data, final String md5StringWithSalt) {
		return verifyMd5WithRandomSalt(data, md5StringWithSalt);
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MD5加密相关  ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */




	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ SHA 加密 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
	/**
	 * 默认使用 SHA-1 20字节 160位
	 * 其他还有:
	 * SHA-224 32字节 224位
	 * SHA-256 32字节 256位
	 * SHA-384 48字节 384位
	 * SHA-512 64字节 512位
	 * 由于它产生的数据摘要的长度更长,因此更难以发生碰撞,因此较之MD5更为安全,它是未来数据摘要算法的发展方向。
	 * 由于SHA系列算法的数据摘要长度较长,因此其运算速度与MD5相比,也相对较慢。
	 */
	/**
	 * SHA 加密
	 *
	 * @param data
	 * @return
	 */
	public static String encryptSHA(final byte[] data) {
		return DigestUtils.sha1Hex(data).toUpperCase();

	}

	/**
	 * SHA 加密,字符串到字符串 <br>
	 * <br>
	 *
	 * @param data
	 * @return
	 */
	public static String encryptSHA(final String data) {
		return DigestUtils.sha1Hex(data).toUpperCase();
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ SHA 加密 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */




	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MAC加密相关 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
	/**
	 * 默认使用 HmacMD5 加密。
	 * 其他还有:
	 * HmacSHA1
	 * HmacSHA256
	 * HmacSHA384
	 * HmacSHA512
	 */
	/**
	 * 初始化 MAC 密钥
	 *
	 * @return MAC 密钥
	 * @throws NoSuchAlgorithmException
	 */
	public static String initMacKey() throws NoSuchAlgorithmException {
		KeyGenerator keyGenerator = KeyGenerator.getInstance(HmacAlgorithms.HMAC_MD5.getName());
		SecretKey secretKey = keyGenerator.generateKey();
		return encryptBase64(secretKey.getEncoded());
	}

	/**
	 * MAC 加密
	 *
	 * @param data 待加密数据
	 * @param key  密钥,可用 initMacKey() 方法生成,也可自定义
	 * @return 加密后数据
	 */
	public static String encryptHMAC(final byte[] data, final String key) {
		HmacUtils hmacMd5 = new HmacUtils(HmacAlgorithms.HMAC_MD5, key);
		return hmacMd5.hmacHex(data).toUpperCase();
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MAC加密相关 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */


	/**
	 * 生成含有随机盐的加密字符串
	 *
	 * @param data 待加密的字符
	 * @return 加密后的字符(含 16 位随机盐),大写
	 */
	private static String encryptMd5WithRandomSalt(String data) {
		Random r = new Random();
		StringBuilder sb = new StringBuilder(16);
		sb.append(r.nextInt(99999999))
				.append(r.nextInt(99999999));
		int len = sb.length();
		if (len < 16) {
			for (int i = 0; i < 16 - len; i++) {
				sb.append("0");
			}
		}
		String salt = sb.toString();
		String md5WithSaltStr = DigestUtils.md5Hex(data + salt);
		char[] cs = new char[48];
		for (int i = 0; i < 48; i += 3) {
			cs[i] = md5WithSaltStr.charAt(i / 3 * 2);
			char c = salt.charAt(i / 3);
			cs[i + 1] = c;
			cs[i + 2] = md5WithSaltStr.charAt(i / 3 * 2 + 1);
		}
		return new String(cs).toUpperCase();
	}

	/**
	 * 校验密码是否正确
	 *
	 * @param data                    待验证的字符(明文)
	 * @param md5StrContainRandomSalt 加密后的字符(含 16 位随机盐)
	 * @return 验证结果
	 */
	private static boolean verifyMd5WithRandomSalt(String data, String md5StrContainRandomSalt) {
		// 32 位加密字符(不含盐)
		char[] cs1 = new char[32];
		// 16 位的随机盐
		char[] cs2 = new char[16];
		for (int i = 0; i < 48; i += 3) {
			cs1[i / 3 * 2] = md5StrContainRandomSalt.charAt(i);
			cs1[i / 3 * 2 + 1] = md5StrContainRandomSalt.charAt(i + 2);
			cs2[i / 3] = md5StrContainRandomSalt.charAt(i + 1);
		}
		String salt = new String(cs2);
		return Objects.equals(DigestUtils.md5Hex(data + salt).toUpperCase(), new String(cs1));
	}

}

Third, the symmetric encryption

Symmetric encryption

Fourth, the asymmetric encryption

Let's look at these two articles to help understand 非对称加密, , 数字签名written in very good shape.

Asymmetric encryption

Encryption online testing tool

Online encryption and decryption tool

Reference Related Articles

Guess you like

Origin blog.csdn.net/qq_34845394/article/details/102759238