Summary of symmetric encryption algorithms: introduction to AES des 3DES SM4 Java implementation

Time:2021-7-29

Password world

If you are a gangster boss and communicate with your subordinates at ordinary times, how can you ensure your information security?

In the first season of detective Shylock, it tells a story about how to detect the encrypted communication of gangs.

Summary of symmetric encryption algorithms: introduction to AES des 3DES SM4 Java implementation

This password uses a password dictionary.

Can the password itself be a book, such as the common Bible, kill a robin, or a map of New York?

The advantage of this encryption method is that if you don’t know the dictionary itself, it can’t be cracked. It’s also very easy to use. You can even change the dictionary with your men regularly.

When it comes to passwords, another story that has to be mentioned is the problem of password decoding during World War II.

During World War II, enigma encryption machine invented by Germany made communication encryption leap from the era of manual handwriting to the era of machine operation, and also made manual decoding powerless.

In order to decipher the German encryption machine, three excellent mathematicians were found from Cambridge: Jeffrey, wilshman and Alan Turing.

Speaking of Turing, I think everyone must know. If you don’t know, I suggest collecting this article and reading it after understanding it.

As the saying goes, only magic can defeat magic. That can make Kibo… Ah, sorry, let Turing come.

Summary of symmetric encryption algorithms: introduction to AES des 3DES SM4 Java implementation

Turing believed that it was feasible to use the crib method in mathematics to crack enigma, and deciphered most of the German intelligence information in the later stage.

In the future, weUse the machine to defeat the machine

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 communications, we need to decrypt.

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

DES algorithm

brief introduction

DES is fully known as data encryption standard, that is, data encryption standard. It is a block algorithm using key encryption. In 1977, it was determined as federal data processing standard (FIPS) by the National Bureau of standards of the federal government of the United States, and authorized to be used in unclassified government communications. Subsequently, this algorithm was widely spread internationally.

Design principles

Two principles of block cipher design are used in Des design: confusion and diffusion. Its purpose is to resist the statistical analysis of the enemy’s cryptosystem.

Confusion is to make the relationship between the statistical characteristics of ciphertext and the value of key as complex as possible, so that the dependence between key and plaintext and ciphertext can not be used by cryptoanalysts.

The role of diffusion is to act the influence of each bit of plaintext on more output ciphertext bits as quickly as possible, so as to eliminate the statistical structure of plaintext in a large number of ciphertext, and make the influence of each bit of key expand to more ciphertext bits as quickly as possible, so as to prevent the key from being decoded paragraph by paragraph.

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

Getting started

Here is the simplest des implementation example.

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;

/**
 *Des tool class
 *
 * @author binbin.hou
 * @since 0.0.6
 */
public final class DesUtil {

    private DesUtil() {
    }

    /**
     * des
     *
     * @since 0.0.6
     */
    private static final String DES = "DES";

    /**
     *Encryption
     *
     *@ param plaintext content to be encrypted
     *@ param password password
     *@ return encryption result
     * @since 0.0.6
     */
    public static byte[] encrypt(String plainText, String password) {
        byte[] bytes = plainText.getBytes();
        return encrypt(bytes, password);
    }

    /**
     *Encryption
     *
     *@ param plaintext content to be encrypted
     *@ param password password
     *@ return encryption result
     * @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 use it to convert deskeyspec to
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey secretKey = keyFactory.generateSecret(desKey);
            //Cipher object actually completes the encryption operation
            Cipher cipher = Cipher.getInstance(DES);
            //Initializing cipher objects with keys
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
            //Now get the data and encrypt it
            //Formal encryption operation
            return cipher.doFinal(plainText);
        } catch (Exception e) {
            throw new SecretRuntimeException(e);
        }
    }

    /**
     *Decryption
     *
     * @param src      byte[]
     * @param password String
     *@ return decryption result
     * @since 0.0.6
     */
    public static byte[] decrypt(byte[] src, String password) {
        try {
            //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 the deskeyspec object to a secretkey object
            SecretKey secretKey = keyFactory.generateSecret(desKey);
            //The cipher object actually completes the decryption operation
            Cipher cipher = Cipher.getInstance(DES);
            //Initializing cipher objects with keys
            cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
            //Really start decryption operation
            return cipher.doFinal(src);
        } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
            throw new SecretRuntimeException(e);
        }
    }

    /**
     *Decryption
     *
     * @param src      byte[]
     * @param password String
     *@ return decryption result
     * @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);
        }
    }

    /**
     *Decryption
     *
     * @param src      byte[]
     * @param password String
     *@ return decryption result
     * @since 0.0.6
     */
    public static String decryptToString(byte[] src, String password) {
        return decryptToString(src, password, "UTF-8");
    }

}

Test code

The test code is as follows:

public static void main(String[] args) {
    //Content to be encrypted
    String STR = "test content";
    //Password, the length should be a multiple of 8
    String password = "01234567";
    byte[] result = DesUtil.encrypt(str, password);
    System. Out. Println ("after encryption:" + hexutil. Bytetohexstring (result));
    //Decrypt the above contents directly
    String decryResult = DesUtil.decryptToString(result, password);
    System. Out. Println ("after decryption:" + decryresult);
}

The log is as follows:

After encryption: 77c25c0143f544cfff102e43bde1abe1
After decryption: test content

Expand reading

For specific algorithm principles, please read:

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

3DES

Algorithm Introduction

3DES (or Triple DES) is the general name of triple data encryption algorithm (TDEA) block cipher.

It is equivalent to applying 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 brutally cracked;

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

Introduction to Java

The tool classes of 3DES are implemented 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;

/**
 *3DES tool class
 *
 * @author binbin.hou
 * @since 0.0.7
 */
public final class TripleDesUtil {

    private TripleDesUtil() {
    }

    /**
     *Algorithm name
     *
     * @since 0.0.7
     */
    private static final String ALGORITHM = "DESede";

    /**
     *Encryption function
     *
     *@ param keybytes encryption key, length 24 bytes
     *@ param plainbytes encrypted data buffer (source)
     *@ return result
     * @since 0.0.7
     */
    public static byte[] encrypt(byte[] keyBytes, byte[] plainBytes) {
        try {
            //Generate key
            SecretKey deskey = new SecretKeySpec(keyBytes, ALGORITHM);
            //Encryption
            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, length 24 bytes
     *@ param plaintext encrypted data buffer (source)
     *@ return result
     * @since 0.0.7
     */
    public static byte[] encrypt(byte[] keyBytes, String plainText) {
        return encrypt(keyBytes, plainText.getBytes());
    }

    /**
     *Decryption function
     *@ param keybytes encryption key, length 24 bytes
     *@ param secretbytes encrypted buffer
     *@ return result
     * @since 0.0.7
     */
    public static byte[] decrypt(byte[] keyBytes, byte[] secretBytes) {
        try {
            //Generate key
            SecretKey deskey = new SecretKeySpec(keyBytes, ALGORITHM);
            //Decryption
            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, length 24 bytes
     *@ param secretbytes encrypted buffer
     *
     *@ 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);
}

Log information:

A60CBC97EEFF2958DF4384215E0838C0
I love China!

Expand reading

For specific algorithm principles, please read:

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

AES algorithm

Algorithm Introduction

Advanced Encryption Standard (AES) in cryptography, also known as Rijndael encryption method, is a block encryption standard adopted by the federal government of the United States.

In 2006, 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 tool class is implemented as follows.

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;

/**
 *3DES tool class
 *
 * @author binbin.hou
 * @since 0.0.7
 */
public final class AesUtil {

    private AesUtil() {
    }

    /**
     *Algorithm name
     *
     * @since 0.0.7
     */
    private static final String ALGORITHM = "AES";

    /**
     *Encrypt the specified plaintext 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 encrypted ciphertext
     *@ param keybytes secret key
     *@ return 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);
        }
    }

    /**
     *Get encryption key
     *
     * @param keySeed seed
     *@ return result
     * @since 0.0.8
     */
    private static SecretKey getSecretKey(byte[] keySeed) {
        try {
            //Avoid random problems in Linux system
            SecureRandom 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);
        }
    }
    
}

Test code

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

Output: I love China!

Expand reading

For specific algorithm principles, please read:

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

SM4 algorithm

Algorithm Introduction

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

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

SM4 algorithm, also known as state secret algorithm. Because it belongs to the Chinese people’s own encryption algorithm, it will be used in domestic finance and other fields.

Introduction to Java

Maven dependency

<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 state secret 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 filling rule, pkcs5padding fills 0 in the absence, nopadding does not fill
     */
    private static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";

    /**
     *ECB encryption mode, no vector
     *@ param algorithmname algorithm name
     *@ 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: the length of ECB ciphertext is not fixed and will change with the length of the encrypted string
     *
     *@ param hexkey hex key (case ignored)
     *@ param plaintext string to be encrypted
     *@ return returns a 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[]
            //This line is used when the encrypted data is a hexadecimal string
            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);
        }
    }

    /**
     *Encryption mode ECB
     *
     *@ param key secret key
     *@ param data data to be encrypted
     *@ return byte array
     * @since 0.0.5
     */
    public static byte[] encryptEcbPadding(byte[] key, byte[] data) {
        try {
            //Claim the ECB code, and judge whether to encrypt or decrypt through the second parameter
            Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(data);
        } catch (Exception exception) {
            throw new SecretRuntimeException(exception);
        }
    }

    //Decryption****************************************

    /**
     *SM4 decryption
     *
     *Decryption mode: ECB
     *@ param hexkey hex key
     *@ param ciphertext hex encrypted string (case ignored)
     *@ return decrypted string
     * @since 0.0.5
     */
    public static String decryptEcb(String hexKey, String cipherText) {
        try {
            //Used to receive the decrypted string
            String decryptStr = "";
            // hexString-->byte[]
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            // hexString-->byte[]
            byte[] cipherData = ByteUtils.fromHexString(cipherText);
            //Decryption
            byte[] srcData = decryptEcbPadding(keyData, cipherData);
            // byte[]-->String
            decryptStr = new String(srcData, ENCODING);
            return decryptStr;
        } catch (Exception exception) {
            throw new SecretRuntimeException(exception);
        }
    }

    /**
     *Decryption
     *
     *@ param key secret key
     *@ param ciphertext ciphertext
     *@ return result
     * @since 0.0.5
     */
    public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) {
        try {
            //Generate the ECB code, and judge whether to encrypt or decrypt through the second parameter
            Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(cipherText);
        } catch (Exception exception) {
            throw new SecretRuntimeException(exception);
        }
    }

    /**
     *Validation data
     * @param hexKey key
     *@ param ciphertext ciphertext
     *@ param plaintext plaintext
     *@ return result
     * @since 0.0.5
     */
    public static boolean verifyEcb(String hexKey, String cipherText, String plainText) {
        try {
            //Used to receive verification results
            boolean flag = false;
            // hexString-->byte[]
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            //Converts a hexadecimal string to an array
            byte[] cipherData = ByteUtils.fromHexString(cipherText);
            //Decryption
            byte[] decryptData = decryptEcbPadding(keyData, cipherData);
            //Convert the original string to byte []
            byte[] srcData = plainText.getBytes(ENCODING);
            //Judge whether the two arrays are consistent
            flag = Arrays.equals(decryptData, srcData);
            return flag;
        } catch (Exception exception) {
            throw new SecretRuntimeException(exception);
        }
    }

}

Test code

System. Out. Println ("start *******************************");
String plainText = "96C63180C2806ED1F47B859DE501215B";
System. Out. Println ("before encryption:" + plaintext);
//Custom 32-bit hex key
String key = "86C63180C2806ED1F47B859DE501215B";
String cipher = encryptEcb(key, plainText);// SM4 encryption
System. Out. Println ("after encryption:" + cipher);
//Verify whether the same data exists before and after encryption
System. Out. Println ("check:" + verifyecb (key, cipher, plaintext));
plainText = decryptEcb(key, cipher);// decrypt
System. Out. Println ("after decryption:" + plaintext);
System. Out. Println ("end ********************************");

Corresponding log:

Start****************************
Before encryption: 96c63180c2806ed1f47b859de501215b
After encryption: 063c352bec7d360da455ebaab2595347d0aa493d2a80a72396771b5585a49f81642626904c036af50b50f92e86cb274
Verification: true
After decryption: 96c63180c2806ed1f47b859de501215b
End****************************

Expand reading

For specific algorithm principles, please read:

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

The fifth largest encryption algorithm

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

Andrew: why, why don’t I know?

Summary of symmetric encryption algorithms: introduction to AES des 3DES SM4 Java implementation

Finally, let’s talk about another common algorithm Base64.

Algorithm Introduction

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

Base64 is a method that can combine any binary data into a string with 64 characters, and the binary data and string data can be converted to each other, which is very convenient.

In practical application, Base64 can not only visualize binary data, but also commonly used to represent the encrypted content of strings.

Java tool class

import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.secret.api.exception.SecretRuntimeException;

import java.io.UnsupportedEncodingException;

/**
 *Base64 tool class
 *
 *Transcoding class
 * @author binbin.hou
 * @since 0.0.4
 */
public final class Base64Util {

    private 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;
    }

    /**
     *Encode the original data into Base64 encoding
     *
     *@ param data data
     * @since 0.0.4
     */
    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;
    }

    /**
     *Decode Base64 encoded data into original data
     *
     *@ param data array
     * @since 0.0.4
     */
    public static byte[] decode(char[] data) {
        int len = ((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;
    }

    /**
     *Code
     *@ param text
     *@ return result
     * @since 0.0.4
     */
    public static char[] encode(String text) {
        if(StringUtil.isEmpty(text)) {
            return new char[]{};
        }
        byte[] data = text.getBytes();

        return encode(data);
    }

    /**
     *Code为字符串
     *
     *@ param text
     *@ return result
     * @since 0.0.4
     */
    public static String encodeToString(String text) {
        if(StringUtil.isEmpty(text)) {
            return text;
        }
        char[] chars = encode(text);

        return new String(chars);
    }

    /**
     *Decode Base64 encoded data into original data
     *
     *@ param text decoding
     * @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 original data
     *
     *@ param text decoding
     *@ param charset code
     * @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:

5oiR54ix5Lit5Zu9IQ==
I love China!

Expand reading

For specific algorithm principles, please read:

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

Summary

In the information age, we have been pursuing two indicators: speed and security (not passion).

Security algorithm will always evolve with the progress of the times. It is a never-ending war of attack and defense.

For all the algorithms in this paper, I have made a unified coding implementation summary, which is convenient for everyone to use. If you are interested, you can follow [old horse roaring west wind] and reply to [encryption] in the background.

In addition, we can talk about irreversible encryption and asymmetric encryption when we have time.

I’m old ma. I look forward to seeing you again next time.

Summary of symmetric encryption algorithms: introduction to AES des 3DES SM4 Java implementation

Recommended Today

Implementation example of go operation etcd

etcdIt is an open-source, distributed key value pair data storage system, which provides shared configuration, service registration and discovery. This paper mainly introduces the installation and use of etcd. Etcdetcd introduction etcdIt is an open source and highly available distributed key value storage system developed with go language, which can be used to configure sharing […]