If you’re a gang boss and you communicate with your people, how do you keep your information safe?

The first series of Sherlock tells the story of how to crack the gangsters’ encrypted communications.

Could the password itself be a book, such as the usual Bible, To Kill a Mockingbird, or a map of New York?

The advantage of this type of encryption is that if you don’t know the dictionary itself, it’s almost impossible to crack. It’s easy to use, and you can even change your dictionary regularly with your staff.

Talking about passwords, another story that has to be mentioned is the problem of code breaking during World War II.

During the Second World War, the Enigma encryption machine invented by Germany made communication encryption leap from the era of manual handwriting to the era of machine operation, which also made manual decoding somewhat impossible.

In order to break the German encryption machine, three brilliant mathematicians were brought in from Cambridge: Geoffrey, Wilshman, and Alain. Turing.

As the saying goes, only magic can defeat magic. That would make Kibo… Ah, excuse me, but let Turing do it.

Turing thought it possible to use the mathematical Crib method to break Enigma, and most of the German intelligence information was deciphered at a later stage.

In later times, we use machines to defeat machines.

# The reversibility of encryption

Encryption algorithms can be divided into: reversible encryption and irreversible encryption; Reversible encryption can be divided into symmetric encryption and asymmetric encryption.

Of course, in general communication, we need to decrypt.

This paper mainly introduces the four most famous encryption algorithms in modern times: DES 3DES AES and SM4.

# The DES algorithm

## Introduction to the

DES Data Encryption Standard (DES) is a kind of block algorithm that encrypts Data by key. In 1977, it was identified as the Federal Data Processing Standard (FIPS) by the National Bureau of Standards of the United States federal government, and authorized to be used in non-secret government communications. Subsequently, the algorithm was widely spread in the world.

## Design principles

The two principles of block cipher design, Confusion and Diffusion, are used in the design of DES, which aims to fight against the statistical analysis of the cipher system by the enemy.

Obfuscation is to complicate as much as possible the relationship between the statistical properties of the ciphertext and the value of the key so that the dependencies between the key and the plaintext and the ciphertext are not available to the cryptanalyser.

The effect of diffusion is to spread the influence of each bit of plaintext to more output ciphertext bits as quickly as possible, so as to eliminate the statistical structure of the plaintext in a large number of ciphertext bits, and to spread the influence of each bit of key to more ciphertext bits as quickly as possible, so as to prevent the key from being deciphered segment by segment.

PS: Basic modern encryption algorithms should follow these two principles, otherwise they will be attacked by statistics.

## Introduction to use

The simplest DES implementation example is provided here.

``import javax.crypto.*; import javax.crypto.spec.DESKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; Public final class DesUtil {private DesUtil() {public final class DesUtil() {public final class DesUtil() {public final class DesUtil() {public final class DesUtil() {public final class DesUtil() {/** * DES ** @since 0.0.6 */ private static final String DES = "DES"; /** * Encrypting ** @Param PlainText * @Param Password * @Return Encrypting * @Since 0.0.6 */ public static byte[] encrypt(String plainText, String password) { byte[] bytes = plainText.getBytes(); return encrypt(bytes, password); } /** * Encrypting ** @Param PlainText * @Param Password * @Return Encrypting * @Since 0.0.6 */ public static byte[] encrypt(byte[] plainText, String password) { try { SecureRandom random = new SecureRandom(); DESKeySpec desKey = new DESKeySpec(password.getBytes()); / / create a key factory, and then use it to convert the DESKeySpec SecretKeyFactory keyFactory = SecretKeyFactory. GetInstance (DES); SecretKey secretKey = keyFactory.generateSecret(desKey); Cipher Cipher = Cipher.getInstance(DES); // Initialize the Cipher object cipher.init(cipher. ENCRYPT_MODE, secretKey, random) with the key; // Now, fetch the data and encrypt it. // Encrypt the data in the CIPHER.DOFINAL (plainText); } catch (Exception e) { throw new SecretRuntimeException(e); }} /** * Decrypt ** @Param SRC byte[] * @Param password String * @Return Decrypt * @Since 0.0.6 */ public static byte[] Decrypt (byte[] SRC, String password) {try {// The DES algorithm requires a trusted random number source SecureRandom random = new SecureRandom(); // create a deskeySpec object deskeySpec desKey = new deskeySpec (password.getBytes()); / / create a key factory SecretKeyFactory keyFactory = SecretKeyFactory. GetInstance (DES); / / convert DESKeySpec object into SecretKey object SecretKey SecretKey. = keyFactory generateSecret (desKey); Cipher Cipher = Cipher.getInstance(DES); // Initialize the Cipher object cipher.init(cipher. DECRYPT_MODE, secretKey, random) with the key; // real start decryption operation return cipher.dofinal (SRC); } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { throw new SecretRuntimeException(e); }} /** * Decrypt ** @Param SRC byte[] * @Param password String * @return Decrypt * @since 0.0.6 */ public static String decryptToString(byte[] src, String password, String charset) { try { byte[] bytes = decrypt(src, password); return new String(bytes, charset); } catch (UnsupportedEncodingException e) { throw new SecretRuntimeException(e); }} /** * Decrypt ** @Param SRC byte[] * @Param password String * @return Decrypt * @since 0.0.6 */ public static String decryptToString(byte[] src, String password) { return decryptToString(src, password, "UTF-8"); }}``

## The test code

The test code is as follows:

``Public static void main(String[] args) {public static void main(String[] args) { String password = "01234567"; byte[] result = DesUtil.encrypt(str, password); System.out.println(" after encryption: "+ HexUtil. ByteToHexString (result)); String decryResult = DesUtil. DecryPtToString (result, password); System.out.println(" decrypt: "+ decryResult); }``

The log is as follows:

``After the encryption: 77 c25c0143f544cfff102e43bde1abe1 decrypted: test content``

DES encryption algorithm introduction and algorithm principle:
http://houbb.github.io/2020/06/17/althgorim-cryptograph-05-des

# 3DES

## Algorithm is introduced

3DES (or Triple DES) is a generic name for the TDEA (Triple Data Encryption Algorithm) block cipher.

It is equivalent to applying the DES encryption algorithm three times to each data block.

Due to the enhancement of computer computing power, the key length of the original DES password becomes easy to be broken by violence;

3DES is designed to provide a relatively simple way to avoid similar attacks by increasing the length of the DES key, rather than designing a completely new block cipher algorithm.

## Introduction to Java

3DES tool class implementation is as follows:

``import com.github.houbb.heaven.constant.CharsetConst; import com.github.houbb.secret.api.exception.SecretRuntimeException; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; /** * @author binbin.hou * @since 0.0.7 */ public final class TripleSutil {private TripleSutil () {} /** * @since 0.0.7 */ private static final String ALGORITHM = "DESede"; /** * Encryption function ** @Param KeyBytes Encryption key, Public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), Byte [] plainBytes) {try {// Generate SecretKey deskey = new SecretKeySpec(keyBytes, ALGORITHM); // Cipher C1 = Cipher.getInstance(ALGORITHM); c1.init(Cipher.ENCRYPT_MODE, deskey); return c1.doFinal(plainBytes); } catch (Exception e1) { throw new SecurityException(e1); }} /** * Encryption function ** @Param KeyBytes Encryption key, Public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), public static byte[] ENCRYPT (byte[] ENCRYPT (KeyBytes), String plainText) { return encrypt(keyBytes, plainText.getBytes()); } /** * Decryption function * @Param KeyBytes Encryption key, Public static byte[] Decrypt (byte[] KeyBytes, Byte [] KeyBytes, Byte [] KeyBytes, Byte [] KeyBytes, Byte [] KeyBytes, Byte [] KeyBytes, Byte [] secretBytes) {try {// Generate secretKey deskey = new secretKeySpec (keyBytes, ALGORITHM); // Decrypt Cipher C1 = Cipher.getInstance(ALGORITHM); c1.init(Cipher.DECRYPT_MODE, deskey); return c1.doFinal(secretBytes); } catch (Exception e1) { throw new SecretRuntimeException(e1); }} /** * Decryption function * @Param KeyBytes Encryption key, Length 24 bytes * @Param SecretBytes encrypted buffer * @Param CharsetName encoding name * * @Return result * @Since 0.0.7 */ public static String decryptToString(byte[] keyBytes, byte[] secretBytes, String charsetName) { try { byte[] bytes = decrypt(keyBytes, secretBytes); return new String(bytes, charsetName); } catch (UnsupportedEncodingException e) { throw new SecretRuntimeException(e); }} /** * Decryption function * @Param KeyBytes Encryption key, @SecretBytes * * @return result * @since 0.0.7 */ public static String DecryPtToString (byte[] keyBytes, byte[] secretBytes) { return decryptToString(keyBytes, secretBytes, CharsetConst.UTF8); }}``

## test

``Public static void main(String[] args) {String text = "I love China!" ; String password = "123456781234567812345678"; byte[] bytes = encrypt(password.getBytes(), text); System.out.println(HexUtil.byteToHexString(bytes)); String plainText = decryptToString(password.getBytes(), bytes); System.out.println(plainText); }``

``A60CBC97EEFF2958DF4384215E0838C0 I love Chinese!``

3DES encryption algorithm introduction and algorithm principle:
http://houbb.github.io/2020/06/17/althgorim-cryptograph-06-3des

# AES algorithm

## Introduction of algorithm

Advanced Encryption Standard (AES) is a block Encryption Standard adopted by the United States federal government.

In 2006, the Advanced Encryption Standard has become one of the most popular algorithms in symmetric key encryption.

This algorithm is more secure than 3DES.

## Introduction to Java

The Java utility class implementation is as follows.

``import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.io.UnsupportedEncodingException; import java.security.SecureRandom; / * * @ * * * 3 des tools author binbin. Hou * @ since 0.0.7 * / public final class AesUtil {private AesUtil () {} / name * * * * algorithm * @since 0.0.7 */ private static final String ALGORITHM = "AES"; /** * Encrypts the specified plainText according to the key. ** @param plainBytes plainText * @param keyBytes password * @return encrypted ciphertext. * @since 0.0.8 */ public static byte[] encrypt(byte[] plainBytes, byte[] keyBytes) { try { SecretKey secretKey = getSecretKey(keyBytes); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(plainBytes); } catch (Exception e) { throw new RuntimeException(e); }} /** * Decrypt the specified ciphertext cipherBytes according to the key. ** @Param cipherBytes encrypt the ciphertext * @Param keyBytes secret key * @return the decrypted plaintext. * @since 0.0.8  */ public static byte[] decrypt(byte[] cipherBytes, byte[] keyBytes) { try { SecretKey secretKey = getSecretKey(keyBytes); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(cipherBytes); } catch (Exception e) { throw new RuntimeException(e); }} /** * getSecretKey ** @Param KeySeed * @Return result * @Since 0.0.8 */ private static SecretKey getSecretKey(byte[] SecureRanDOM = secureRanDOM. GetInstance ("SHA1PRNG"); secureRandom.setSeed(keySeed); KeyGenerator generator = KeyGenerator.getInstance("AES"); generator.init(secureRandom); return generator.generateKey(); } catch (Exception e) { throw new RuntimeException(e); }}}``

## The test code

``Public static void main (String [] args) throws UnsupportedEncodingException {String text = "I love China!" ; 256-32 bytes / / key, String password = "uBdUx82vPHkDKb284d7NkjFoNcKWBuka"; byte[] bytes = encrypt(text.getBytes(), password.getBytes()); String text2 = new String(decrypt(bytes, password.getBytes()), "UTF-8"); System.out.println(text2); }``

Export: I love China!

Introduction to AES encryption algorithm and algorithm principle:
http://houbb.github.io/2020/06/17/althgorim-cryptograph-07-aes

# SM4 algorithm

## Introduction of algorithm

SM4 is a block cipher algorithm with a block length of 128 bits (16 bytes, 4 words) and a key length of 128 bits (16 bytes, 4 words).

The encryption and decryption process adopts 32 rounds of iteration mechanism (similar to DES and AES), and each round needs a round key (similar to DES and AES).

SM4 algorithm, also known as the national secret algorithm. Because this is the Chinese own encryption algorithm, domestic finance and other fields will be used.

## Introduction to Java

### Maven rely on

``< the dependency > < groupId > org. Bouncycastle < / groupId > < artifactId > bcprov - jdk15on < / artifactId > < version > 1.59 < / version > </dependency>``

### Tool encapsulation

``import com.github.houbb.secret.api.exception.SecretRuntimeException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.security.Key; import java.security.Security; import java.util.Arrays; / * * * * * @ Sm4 countries close algorithm author binbin. Hou * @ since 0.0.5 * / public final class Sm4Util {private Sm4Util () static {{} Security.addProvider(new BouncyCastleProvider()); } private static final String ENCODING = "UTF-8"; private static final String ALGORITHM_NAME = "SM4"; /** * PKCS5PADDING_NOPADDING_NOPADDING_NOPADDING_NOPADDING_NOPADDING_NOPADDING_NOPADDING_NOPADDING_NO */ private static final String Algorithm_Name_ECB_Padding = "SM4/ECB/PKCS5Padding"; /** * ECB encryption mode, Vectorless * @Param AlgorithmName * @Param mode mode * @Param key key * @Return result */ private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); cipher.init(mode, sm4Key); return cipher; } /** * SM4 Encryption * Encryption mode: ECB ciphertext length is not fixed, Variable as the length of the encrypted string changes * * @Param hexKey hexadecimal key (ignoring case) * @Param plainText string to encrypt * @return return hexadecimal encrypted string * @since 0.0.5 */ public static String encryptEcb(String hexKey, String plainText) { try { String cipherText = ""; // hexadecimal string -->byte[] byte[] keyData = ByteUtils.fromHexString(hexKey); // String-->byte[] // byte[] srcData = plainText.getBytes(ENCODING); // Encrypted array byte[] CipherArray = ENCRYPTECBPADDING (keyData, srcData); // byte[]-->hexString cipherText = ByteUtils.toHexString(cipherArray); return cipherText; } catch (Exception exception) { throw new SecretRuntimeException(exception); }}} /** * ECB ** @Param Key * @Param Data * @Return byte array * @Since 0.0.5 */ public static byte[] encryptEcbPadding(byte[] key, Cipher Cipher = GenerateECBcipher (Algorithm_Name_ECB_Padding, Algorithm_Name_ECB_Padding, Algorithm_Name_ECB_Padding, Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } catch (Exception exception) { throw new SecretRuntimeException(exception); }} / / decryption * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * * * * sm4 decryption decryption mode: Adopt ECB * @Param Hexkey hexadecimal key * @Param Ciphertext hexadecimal encrypted string (ignoring case) * @Return decrypted string * @Since 0.0.5 */ public static String decryptECB (String hexKey, String cipherText) {try {// Use to receive decrypted String decryptStr = ""; // hexString-->byte[] byte[] keyData = ByteUtils.fromHexString(hexKey); // hexString-->byte[] byte[] cipherData = ByteUtils.fromHexString(cipherText); // decrypt byte[] srcData = DecryPtecBPadding (keyData, cipherData); // byte[]-->String decryptStr = new String(srcData, ENCODING); return decryptStr; } catch (Exception exception) { throw new SecretRuntimeException(exception); }} /** * Decrypt ** @Param Key * @Param CipherText * @Return result * @Since 0.0.5 */ public static byte[] decryptEcbPadding(byte[] key, Cipher Cipher = GenerateCipher (Algorithm_Name_ECB_Padding, Algorithm_Name_ECB_Padding, Cipher.DECRYPT_MODE, key); return cipher.doFinal(cipherText); } catch (Exception exception) { throw new SecretRuntimeException(exception); }} /** * Verify data * @Param hexKey key * @Param cipherText * @Param plainText * @return result * @since 0.0.5 */ public Static Boolean verifyECB (String hexKey, String cipherText, String plainText) {try {// For receiving check results Boolean flag = false; // hexString-->byte[] byte[] keyData = ByteUtils.fromHexString(hexKey); // Convert a hexadecimal string to an array byte[] CipherData = ByteUtils.FromHexString (CipherText); // decrypt byte[] DecryPtData = DecryPtecBPadding (keyData, cipherData); // Byte [] Byte [] SRCData = PlainText.getBytes (ENCODING); Flag = Arrays.equals(DecryPtData, srcData); return flag; } catch (Exception exception) { throw new SecretRuntimeException(exception); }}}``

## The test code

``System. The out. Println (" start * * * * * * * * * * * * * * * * * * * * * * * * * * * * "); String plainText = "96C63180C2806ED1F47B859DE501215B"; System.out.println(" before encryption: "+ plainText); / / custom 32-bit hexadecimal secret key String key = "86 c63180c2806ed1f47b859de501215b"; String cipher = encryptEcb(key, plainText); // SM4 encryption System.out.println(" after encryption: "+ cipher); Println (" Verify: "+ VerifyECB (Key, Cipher, PlainText)); plainText = decryptEcb(key, cipher); // decrypt System.out.println(" decrypted: "+ plainText); End System. Out. Println (" * * * * * * * * * * * * * * * * * * * * * * * * * * * * ");``

Corresponding log:

``Start * * * * * * * * * * * * * * * * * * * * * * * * * * * * before encryption: after the 96 c63180c2806ed1f47b859de501215b encryption: After the 063 c352bcec7d360da455ebaab2595347d0aa493d2a80a72396771b5585a49f81642326904c036af50b50f92e86cb274 check: true decryption: 96 c63180c2806ed1f47b859de501215b end * * * * * * * * * * * * * * * * * * * * * * * * * * * *``

SM4 encryption algorithm introduction and algorithm principle:
http://houbb.github.io/2020/06/17/althgorim-cryptograph-04-sm4

# The fifth encryption algorithm

Of course, isn’t it common sense that there are five of the four encryption algorithms?

Andrew: why, why didn’t I know?

Let’s finish by talking about Base64, another common algorithm.

## Algorithm is introduced

Strictly speaking, Base64 is not used for encryption, but more for encoding and decoding.

Base64 is a method of combining any Binary data into strings using 64 characters. The Binary data and string data can be converted into each other conveniently.

In practice, Base64 is used to represent the contents of the encoded string, in addition to visualizing the Binary data.

## Java tools

``import com.github.houbb.heaven.util.lang.StringUtil; import com.github.houbb.secret.api.exception.SecretRuntimeException; import java.io.UnsupportedEncodingException; Public final class Base64Util {private Base64Util() {public final class Base64Util() {public final class Base64Util() {public final class Base64Util() {  private static final char[] ALPHABET_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray(); private static final byte[] CODES = new byte[256]; static { for (int i = 0; i < 256; i++) { CODES[i] = -1; } for (int i = 'A'; i <= 'Z'; i++) { CODES[i] = (byte) (i - 'A'); } for (int i = 'a'; i <= 'z'; i++) { CODES[i] = (byte) (26 + i - 'a'); } for (int i = '0'; i <= '9'; i++) { CODES[i] = (byte) (52 + i - '0'); } CODES['+'] = 62; CODES['/'] = 63; } /** * public static char[] encode(byte[] data) {char[] out = new char[((data.length + 2) / 3) * 4]; for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & (int) data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & (int) data[i + 2]); quad = true; } out[index + 3] = ALPHABET_CHARS[(quad ? (val & 0x3F) : 64)]; val >>= 6; out[index + 2] = ALPHABET_CHARS[(trip ? (val & 0x3F) : 64)]; val >>= 6; out[index + 1] = ALPHABET_CHARS[val & 0x3F]; val >>= 6; out[index + 0] = ALPHABET_CHARS[val & 0x3F]; } return out; } /** * public static byte[] decode(char[] data) {int len = 1; public static byte[] decode(char[] data) {int len = 1 ((data.length + 3) / 4) * 3; if (data.length > 0 && data[data.length - 1] == '=') { --len; } if (data.length > 1 && data[data.length - 2] == '=') { --len; } byte[] out = new byte[len]; int shift = 0; int accum = 0; int index = 0; for (char datum : data) { int value = CODES[datum & 0xFF]; if (value >= 0) { accum <<= 6; shift += 6; accum |= value; if (shift >= 8) { shift -= 8; out[index++] = (byte) ((accum >> shift) & 0xff); } } } if (index ! = out.length) { throw new SecretRuntimeException("miscalculated data length!" ); } return out; Public static char[] encode(String text) {public static char[] encode(String text) {public static char[] encode(String text) { if(StringUtil.isEmpty(text)) { return new char[]{}; } byte[] data = text.getBytes(); return encode(data); Public static String encodeToString(String text) {public static String encodeToString(String text) {public static String encodeToString(String text) { if(StringUtil.isEmpty(text)) { return text; } char[] chars = encode(text); return new String(chars); Public static byte[] decode(String text) {** * @param text * @since 0.0.4 */ public static byte[] decode(String text) { if(StringUtil.isEmpty(text)) { return new byte[]{}; } char[] chars = text.toCharArray(); return decode(chars); } /** * Decode Base64 encoded data into raw data ** @Param text decoding * @Param charset encoding * @Since 0.0.4 */ public static String decodeToString(String text, String charset) { try { byte[] bytes = decode(text); return new String(bytes, charset); } catch (UnsupportedEncodingException e) { throw new SecretRuntimeException(e); }}}``

## test

``Public static void main(String[] args) {String text = "I love China!" ; String base64 = encodeToString(text); System.out.println(base64); String decode64 = decodeToString(base64, "UTF-8"); System.out.println(decode64); }``

The output is as follows:

``I love China!``

Base64 encryption algorithm introduction and algorithm principle:
http://houbb.github.io/2020/06/17/althgorim-cryptograph-03-base64

# summary

In the information age, two things have always been sought: speed and security (not passion).

Security algorithm is always evolving with the progress of The Times, which is a never-ending offensive and defensive war.

For all the algorithms in this paper, I have done a unified coding to achieve the summary, easy to use. Interested can pay attention to [old horse roar west wind], the background reply [encryption] can be obtained.

In addition, we can talk a little bit about irreversible encryption, and asymmetric encryption sometime.

I am an old horse, looking forward to the next meeting with you.