Several common encryption algorithms

Keywords: Java Apache codec Mac

Article directory


All the following codes are based on jdk8

All Apache based implementations need to introduce the following package:

<!-- apache.codec:Tool class package of coding method -->
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

I. encoding format (this is not encryption in principle, but it is quite common)

Coding format algorithm

2. Message digest algorithm

Message digest algorithm

Based on the above encoding format algorithm and message digest algorithm, a basic encryption tool is written. Symmetric encryption and asymmetric encryption have separate tool classes, as you can see below.

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;

/**
 * Basic coding tool class
 * <br/>
 * It includes the following types of encryption:
 * <ul>
 *     <li>Base64</li>
 *     <li>URLEncoder,URLDecoder</li>
 *     <li>MD5</li>
 *     <li>MD5 Add random salt</li>
 *     <li>SHA</li>
 *     <li>MAC</li>
 * </ul>
 * <p>
 * Note: < br >
 * Base64 Encryption is reversible, which is generally used to code information transmission, and even to convert pictures into strings and send them to the front-end display. Be careful not to use it to send confidential information! <br>
 * MD5,SHA,MAC These three encryption algorithms are irreversible encryption, and we usually only use them as the basis of encryption. The above three kinds of encryption are not reliable.
 * <p>
 * Created by: leigq < br >
 * Creation time: October 23, 2017 10:39:06 PM < br >
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BaseCoderUtils {
	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ BASE64 Coding and decoding */

	/**
	 * BASE64 encryption
	 * <br/>
	 *
	 * @param binaryData Binary data to be encrypted
	 * @return Encrypted string
	 */
	public static String encryptBase64(final byte[] binaryData) {
		// Android has its own implementation. Because Android can't use Apache's implementation, it can only use its own implementation. Note that Base64.CRLF corresponds to Apache's default mode!
		// return Base64.encodeToString(key, Base64.CRLF);
		return Base64Utils.encodeToString(binaryData);
	}

	/**
	 * BASE64 Decrypt
	 * <br/>
	 *
	 * @param base64String Encrypted string
	 * @return Raw binary data
	 */
	public static byte[] decryptBase64(final String base64String) {
		// Android's own implementation
		// return Base64.decode(key, Base64.CRLF);
		return Base64Utils.decodeFromString(base64String);
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ BASE64 Encoding and decoding */






	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ URL Coding and decoding */

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

	/**
	 * Decode URL
	 */
	public static String decodeURL(final String data) {
		String target;
		try {
			target = URLDecoder.decode(data, StandardCharsets.UTF_8.name());
		} catch (Exception e) {
			log.error("Error decoding!", e);
			throw new RuntimeException(e);
		}
		return target;
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ URL Encoding and decoding */







	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MD5 Encryption related */

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

	/**
	 * MD5 Encryption, string to string
	 *
	 * @param data
	 * @return Capitalization
	 */
	public static String encryptMD5(final String data) {
		return encryptMD5(data.getBytes());
	}

	/**
	 * 3 Secondary MD5 encryption, string to string
	 *
	 * @param data
	 * @return Capitalization
	 */
	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;
	}

	/**
	 * Generate encrypted string with random salt
	 *
	 * @param data Characters to be encrypted
	 * @return Encrypted characters (including 16 bit random salt), uppercase
	 */
	public static String encryptMD5WithRandomSalt(final String data) {
		return encryptMd5WithRandomSalt(data);
	}

	/**
	 * Verify that the password is correct
	 *
	 * @param data              Characters to be verified (clear text)
	 * @param md5StringWithSalt Encrypted characters (including 16 bit random salt)
	 * @return Verification results
	 */
	public static boolean verifyMD5WithRandomSalt(final String data, final String md5StringWithSalt) {
		return verifyMd5WithRandomSalt(data, md5StringWithSalt);
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MD5 Encryption correlation */




	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ SHA Encryption */
	/**
	 * SHA-1 20 bytes 160 bits are used by default
	 * Others include:
	 * SHA-224 32 Byte 224 bits
	 * SHA-256 32 Byte 256 bits
	 * SHA-384 48 Byte 384 bits
	 * SHA-512 64 Byte 512 bit
	 * Because the length of data digest generated by it is longer, it is more difficult to collide, so it is more secure than MD5, and it is the development direction of data digest algorithm in the future.
	 * Because the data summary length of SHA series algorithm is long, its operation speed is relatively slow compared with MD5.
	 */
	/**
	 * SHA encryption
	 *
	 * @param data
	 * @return
	 */
	public static String encryptSHA(final byte[] data) {
		return DigestUtils.sha1Hex(data).toUpperCase();

	}

	/**
	 * SHA Encryption, string to string < br >
	 * <br>
	 *
	 * @param data
	 * @return
	 */
	public static String encryptSHA(final String data) {
		return DigestUtils.sha1Hex(data).toUpperCase();
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ SHA Encryption */




	/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MAC Encryption related */
	/**
	 * HmacMD5 encryption is used by default.
	 * Others include:
	 * HmacSHA1
	 * HmacSHA256
	 * HmacSHA384
	 * HmacSHA512
	 */
	/**
	 * Initialize MAC key
	 *
	 * @return MAC secret key
	 * @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 encryption
	 *
	 * @param data Data to be encrypted
	 * @param key  Key, which can be generated by initMacKey() method or customized
	 * @return Encrypted data
	 */
	public static String encryptHMAC(final byte[] data, final String key) {
		HmacUtils hmacMd5 = new HmacUtils(HmacAlgorithms.HMAC_MD5, key);
		return hmacMd5.hmacHex(data).toUpperCase();
	}
	/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ MAC Encryption correlation */


	/**
	 * Generate encrypted string with random salt
	 *
	 * @param data Characters to be encrypted
	 * @return Encrypted characters (including 16 bit random salt), uppercase
	 */
	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();
	}

	/**
	 * Verify that the password is correct
	 *
	 * @param data                    Characters to be verified (clear text)
	 * @param md5StrContainRandomSalt Encrypted characters (including 16 bit random salt)
	 * @return Verification results
	 */
	private static boolean verifyMd5WithRandomSalt(String data, String md5StrContainRandomSalt) {
		// 32-bit encrypted characters (without salt)
		char[] cs1 = new char[32];
		// 16 bit random salt
		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));
	}

}

3. Symmetric encryption

Symmetric encryption

IV. asymmetric encryption

Let's take a look at these two articles to help understand asymmetric encryption and digital signature. They are well written.

Asymmetric encryption

Online encryption test tool

Online encryption and decryption tool

Refer to related articles

Posted by robviperx on Sat, 26 Oct 2019 02:56:32 -0700