Symmetric encryption algorithm

Posted by vaibhavs on Fri, 05 Jun 2020 09:50:25 +0200

concept

In the symmetric encryption algorithm, the data sender processes the plaintext (original data) and the encryption key together through a special encryption algorithm, which makes it become a complex encrypted text to be sent out. After receiving the ciphertext, if the receiver wants to interpret the original text, it needs to decrypt the ciphertext with the encryption used key and the inverse algorithm of the same algorithm, so that it can be restored to readable plaintext. In the symmetric encryption algorithm, there is only one key, which is used to encrypt and decrypt data in both sending and receiving, which requires the decryptor to know the encryption key.

Advantages and disadvantages

Advantages: open algorithm, small calculation, fast encryption speed and high encryption efficiency
Disadvantages:
- both parties of the transaction use the same key, and the security is not guaranteed.
- every time a pair of users use symmetric encryption algorithm, they need to use a unique key that others don't know, which will make the number of keys owned by both the sender and the receiver increase geometrically, and key management becomes the burden of users. Symmetric encryption algorithm is difficult to use in distributed network system, mainly because of the difficulty of key management and high cost.

Common symmetric encryption algorithms

DES

The full name of DES algorithm is Data Encryption Standard, that is, Data encryption algorithm. It was researched and published by IBM in 1975. There are three entry parameters of DES algorithm: Key, Data and Mode. Among them, Key is the working Key of DES algorithm with 8 bytes of 64 bits in total; Data is also the Data to be encrypted or decrypted with 8 bytes of 64 bits; Mode is the working Mode of DES with two types: encryption or decryption.
DES algorithm changes 64 bit plaintext input block into 64 bit ciphertext output block, and its key is also 64 bit. Its algorithm is mainly divided into two steps:
(1) Initial replacement
Its function is to recombine the input 64 bit data block by bit, and divide the output into two parts, l0 and R0. Each part is 32 bits long. Its replacement rule is to change the 58th bit of the input to the first bit, and the 50th bit to the second bit And so on, the last is the seventh. L0 and R0 are the two parts after the transposition output. L0 is the left 32-bit of the output, and R0 is the right 32-bit. For example, set the input value before the transposition to D1D2D3 D64, the result after initial replacement is: L0=D58D50 D8;R0=D57D49…… D7.

(2) Inverse permutation
After 16 iterations, L16 and R16 are obtained, which are used as input to perform inverse permutation. The inverse permutation is exactly the inverse operation of the initial permutation, so the ciphertext output is obtained.

3DES

3DES (or Triple DES) is a general term for block cipher of Triple Data Encryption Algorithm (TDEA). It is equivalent to applying three DES encryption algorithms to each data block. Due to the enhancement of the computing power of the computer, the key length of the original des password is easy to be brutally cracked; 3DES is designed to provide a relatively simple method, that is, to avoid similar attacks by increasing the key length of DES, rather than designing a new block cipher algorithm.
Three 56 bit keys are used to encrypt the data three times. 3DES (Triple DES) is the encryption algorithm for the transition from des to AES (in 1999, NIST designated 3-DES as the transitional encryption standard).
The specific implementation is as follows: let Ek() and Dk() represent the encryption and decryption process of DES algorithm, K represents the key used by DES algorithm, P represents plaintext, C represents ciphertext, as follows:
3DES encryption process: C=Ek3(Dk2(Ek1 §))
3DES decryption process: P=Dk1(EK2(Dk3))

AES

AES (Advanced Encryption Standard) is the most common symmetric encryption algorithm (used for encrypted transmission of wechat applets). Symmetric encryption algorithm means that encryption and decryption use the same key.

AES is the block cipher. The block cipher is to divide the plaintext into a group and a group. Each group has the same length. One group of data is encrypted each time until the whole plaintext is encrypted. In the AES Standard Specification, the packet length can only be 128 bits, that is, each packet is 16 bytes (8 bits per byte). The length of the key can be 128 bits, 192 bits, or 256 bits. The number of recommended encryption rounds varies with the length of the key.

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

public class DESTest {

    private static final String str = "DES";
    private static final String Algorithm = "DESede";
    private static final String Algo = "AES/ECB/PKCS5Padding";


    /**
     * DES encryption
     * @param src
     * @param password
     * @return
     */
    private static byte[] encrypt(byte[] src, String password) {
        try {
            //DES algorithm requires a trusted random number source
            SecureRandom random = new SecureRandom();
            // Create a deskyspec object
            DESKeySpec desKey = new DESKeySpec(password.getBytes());
            //Create a key factory, and use it to convert the deskyspec to a secret key
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(str);
            SecretKey secretKey = keyFactory.generateSecret(desKey);
            //Cipher object actually completes encryption operation
            Cipher cipher = Cipher.getInstance(str);
            //Initializing Cipher object with secret key, ENCRYPT_MODE a constant used to initialize Cipher to encryption mode
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
            //Encrypt data
            return cipher.doFinal(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DES decrypt
     * @param src
     * @param password
     * @return
     */
    private static byte[] decrypt(byte[] src, String password) {
        try {
            //DES algorithm requires a trusted random number source
            SecureRandom random = new SecureRandom();
            // Create a deskyspec object
            DESKeySpec desKey = new DESKeySpec(password.getBytes());
            //Create a key factory, and then use it to convert deskyspec to secret key
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(str);
            SecretKey secretKey = keyFactory.generateSecret(desKey);
            // Cipher object actually completes the decryption operation
            Cipher cipher = Cipher.getInstance(str);
            // Initializing Cipher object with key
            cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
            // Decrypt data
            return cipher.doFinal(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 3DES Encrypt data
     * @param keyByte
     * @param src
     * @return
     */
    private static byte[] encrypt(byte[] keyByte, byte[] src) {
        try {
            //Generate key
            SecretKey deskey = new SecretKeySpec(keyByte, Algorithm);
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            //Encrypt data
            return c1.doFinal(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 3DES Decrypt data
     * @param keyByte
     * @param src
     * @return
     */
    private static byte[] decrypt(byte[] keyByte, byte[] src) {
        try {
            //Generate key
            SecretKey deskey = new SecretKeySpec(keyByte, Algorithm);
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.DECRYPT_MODE, deskey);
            //decrypt
            return c1.doFinal(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * AES encryption
     * @param data
     * @param key
     * @return
     */
    private static byte[] encrypt(String data, Key key) {
        try {
            Cipher cipher = Cipher.getInstance(Algo);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(data.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES decrypt
     * @param result
     * @param Key
     * @return
     */
    private static byte[] decrypt(byte[] result, Key Key) {
        try {
            Cipher cipher = Cipher.getInstance(Algo);
            cipher.init(Cipher.DECRYPT_MODE, Key);
            return cipher.doFinal(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES Generate Key
     * @return
     */
    private static Key createKey() {
        try {
            //Generate key
            KeyGenerator keyGenerator;
            //Construct key generator, specify AES as large, case insensitive
            keyGenerator = KeyGenerator.getInstance("AES");
            //Generate a 128 bit random source based on the incoming byte array
            keyGenerator.init(128);
            //Generate original symmetric key
            SecretKey secretKey = keyGenerator.generateKey();
            //Get byte array of original symmetric key
            byte[] keyBytes = secretKey.getEncoded();
            //Key conversion, generating AES key according to byte array
            return new SecretKeySpec(keyBytes, "AES");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES Encryption transcoding via base64
     * @param content
     * @param password
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String password) throws Exception {
        try {
            byte[] raw = password.getBytes("UTF-8");
            if (raw.length != 16) {
                throw new IllegalArgumentException("Invalid key size. " + password + ", secret key token Length is not 16 bits");
            }
            javax.crypto.spec.SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            javax.crypto.Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            // zero
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec,
                    new javax.crypto.spec.IvParameterSpec(new byte[16]));
            byte[] fina = cipher.doFinal(content.getBytes("UTF-8"));
            return new String(org.apache.commons.codec.binary.Base64.encodeBase64(fina));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES Decryption via base64 transcoding
     * @param content
     * @param password
     * @return
     * @throws Exception
     */
    public static String decrypt(String content, String password) throws Exception {
        try {
            byte[] raw = password.getBytes("UTF-8");
            if (raw.length != 16) {
                throw new IllegalArgumentException("Invalid key size. " + password + ", secret key token Length is not 16 bits");
            }
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
            byte[] toDecrypt = org.apache.commons.codec.binary.Base64.decodeBase64(content.getBytes());
            byte[] original = cipher.doFinal(toDecrypt);
            return new String(original, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        /* DES
        String password = "12345678";
        String data = "Hello World";
        byte[] encryptData = encrypt(data.getBytes(), password);
        System.out.println("encryptData = " + new String(encryptData));
        byte[] decryptData = decrypt(encryptData, password);
        System.out.println("decryptData = " + new String(decryptData));*/

        /* 3DES
        //Add a new security algorithm. If you use JCE, you need to add it
        Security.addProvider(new SunJCE());
        //24 Byte key
        final byte[] keyBytes = {
                0x11, 0x22, 0x4F, 0x58,
                (byte) 0x88, 0x10, 0x40, 0x38,
                0x28, 0x25, 0x79, 0x51,
                (byte) 0xCB, (byte) 0xDD, 0x55, 0x66,
                0x77, 0x29, 0x74, (byte) 0x98,
                0x30, 0x40, 0x36, (byte) 0xE2
        };
        String src = "Hello World";
        byte[] encryptData = encrypt(keyBytes, src.getBytes());
        System.out.println("encryptData: " + new String(encryptData));

        byte[] decryptData = decrypt(keyBytes,encryptData);
        System.out.println("decryptData: " + new String(decryptData));*/

        /* AES
        String src = "Hello World";
        Key key = createKey();
        byte[] encryptData = encrypt(src, key);
        System.out.println("encryptData: " + new String(encryptData));
        byte[] decryptData = decrypt(encryptData, key);
        System.out.println("decryptData: " + new String(decryptData));*/


        /* Output through BASE64
        try {
            String encryptData = encrypt("Hello World", "123456789abcdefg");
            System.out.println(encryptData);
            System.out.println(decrypt(encryptData,"123456789abcdefg"));
        } catch (Exception e) {
            e.printStackTrace();
        }*/
    }
}

reference resources: https://blog.csdn.net/qq_28205153/article/details/55798628
http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html

Topics: Apache codec network Java