Symmetric encryption and asymmetric encryption

Posted by fireMind on Wed, 09 Mar 2022 11:45:34 +0100

A safe way of communication needs to meet the following three conditions at the same time

1. Integrity, that is, the message has not been tampered with halfway. 2. Confidentiality, which cannot be decrypted by a third party. 3. Authentication. The receiver of the message can determine who sent the message.

Symmetric encryption

The same key used by both parties can be encrypted and decrypted. This encryption method is called symmetric encryption, also known as single key encryption.

Advantages: fast speed. Symmetric encryption is usually used when the message sender needs to encrypt a large amount of data. The algorithm is open, the amount of calculation is small, the encryption speed is fast and the encryption efficiency is high.

Disadvantages: before data transmission, the sender and receiver must agree on the secret key, and then both sides can keep the secret key. Secondly, if one party's secret key is leaked, the encrypted information is not safe. In addition, every time a pair of users use a symmetric encryption algorithm, they need to use a unique secret key that others do not know, which will make the number of keys owned by the receiving and sending sides huge, and key management becomes a burden for both sides.

The commonly used algorithms in symmetric encryption algorithms are DES, AES, etc.

AES: the length of the key can be 128, 192 and 256 bits, that is, 16 bytes, 24 bytes and 32 bytes

DES: the length of the key is 64 bits and 8 bytes.

des encryption and decryption in java:

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class DESUtil {
    public static final String DES = "DES";
    public static final String charset = null; // Coding format; Default null is GBK
    public static final int keysizeDES = 0;

    private static DESUtil instance;

    private DESUtil() {
    }

    // Single case
    public static DESUtil getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new DESUtil();
                }
            }
        }
        return instance;
    }

    /**
     * Encryption using DES
     */
    public String encode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, true);
    }

    /**
     * Decryption using DES
     */
    public String decode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, false);
    }

    // Use KeyGenerator bidirectional encryption, DES/AES. Note that when converting to a string, it is to convert binary to hexadecimal format string, not directly, because there will be errors
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // Convert binary to hexadecimal
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // Convert hexadecimal to binary
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}

AES encryption and decryption in java:

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
    public static final String AES = "AES";
    public static final String charset = null; // Coding format; Default null is GBK
    public static final int keysizeAES = 128;

    private static AESUtil instance;

    private AESUtil() {
    }

    // Single case
    public static AESUtil getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new AESUtil();
                }
            }
        }
        return instance;
    }

    /**
     * Encryption using AES
     */
    public String encode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, true);
    }

    /**
     * Decryption using AES
     */
    public String decode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, false);
    }

    // Use KeyGenerator bidirectional encryption, DES/AES. Note that when converting to a string, it is to convert binary to hexadecimal format string, not directly, because there will be errors
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // Convert binary to hexadecimal
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // Convert hexadecimal to binary
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}

Asymmetric encryption

A pair of keys consists of a public key and a private key (many pairs of keys can be used). The private key decrypts the public key encrypted data, and the public key decrypts the private key encrypted data (the private key and public key can encrypt and decrypt each other). The private key can only be kept by one party and cannot be leaked. The public key can be handed over to any requestor.

The commonly used algorithms in asymmetric encryption algorithms are RSA and so on

Disadvantages: slow speed

Advantages: Safety

rsa encryption and decryption in java:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

import javax.crypto.Cipher;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RSA_Encrypt {
    /** Specify the encryption algorithm as DESede */
    private static String ALGORITHM = "RSA";
    /** Specifies the size of the key */
    private static int KEYSIZE = 1024;
    /** Specify the public key to store the file */
    private static String PUBLIC_KEY_FILE = "PublicKey";
    /** Specify the private key to store the file */
    private static String PRIVATE_KEY_FILE = "PrivateKey";

    /**
     * Generate key pair
     */
    private static void generateKeyPair() throws Exception {
        /** RSA The algorithm requires a trusted random number source */
        SecureRandom sr = new SecureRandom();
        /** Create a KeyPairGenerator object for the RSA algorithm */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /** Initialize the KeyPairGenerator object using the random data source above */
        kpg.initialize(KEYSIZE, sr);
        /** Generate key pair */
        KeyPair kp = kpg.generateKeyPair();
        /** Get public key */
        Key publicKey = kp.getPublic();
        /** Get private key */
        Key privateKey = kp.getPrivate();
        /** Write the generated object to the file with the key */
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(
                PUBLIC_KEY_FILE));
        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(
                PRIVATE_KEY_FILE));
        oos1.writeObject(publicKey);
        oos2.writeObject(privateKey);
        /** Empty the cache and close the file output stream */
        oos1.close();
        oos2.close();
    }

    /**
     * Encryption method source: source data
     */
    public static String encrypt(String source) throws Exception {
        generateKeyPair();
        /** Read out the public key object in the file */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /** Get Cipher object to realize RSA encryption of source data */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /** Perform encryption operation */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    /**
     * Decryption algorithm cryptograph: ciphertext
     */
    public static String decrypt(String cryptograph) throws Exception {
        /** Read out the private key object in the file */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        /** Get the Cipher object and RSA decrypt the data encrypted with the public key */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b1 = decoder.decodeBuffer(cryptograph);
        /** Perform decryption operation */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    public static void main(String[] args) throws Exception {
        String source = "Hello World!";// String to encrypt
        String cryptograph = encrypt(source);// Generated ciphertext
        System.out.println(cryptograph);
        System.out.println("=====================");
        String target = decrypt(cryptograph);// Decrypt ciphertext
        System.out.println(target);
    }
}

Message digest (hash operation, hash operation)

Generate Message digest (encrypted Message digest) for a Message to prevent tampering. The result of encrypting the same string multiple times is the same and irreversible.

Common algorithms: md5,sha1

Using md5 encryption and decryption in java:

import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class MD5Util {
    public static final String MD5 = "MD5";
    public static final String HmacMD5 = "HmacMD5";
    public static final String charset = null; // Coding format; Default null is GBK

    private static MD5Util instance;

    private MD5Util() {
    }

    // Single case
    public static MD5Util getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new MD5Util();
                }
            }
        }
        return instance;
    }

    /**
     * Encryption using MD5 method (no password)
     */
    public String encode(String res) {
        try {
            MessageDigest md = MessageDigest.getInstance(MD5);
            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Use MD5 method for encryption (password can be set)
     */
    public String encode(String res, String key) {
        try {
            SecretKey sk = null;
            if (key == null) {
                KeyGenerator kg = KeyGenerator.getInstance(HmacMD5);
                sk = kg.generateKey();
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                sk = new SecretKeySpec(keyBytes, HmacMD5);
            }
            Mac mac = Mac.getInstance(HmacMD5);
            mac.init(sk);
            byte[] result = mac.doFinal(res.getBytes());
            return BASE64Util.getInstance().encode(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

Using sha1 encryption and decryption in java:

import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * Encryption using SHA1 method < br / >
 * SHA1 Method encryption is irreversible and cannot be decrypted. If you want to decrypt, you must use violent decryption < br / >
 * <p/>
 * res parameter in method: original data < br / >
 * The key parameter in the method: the key, which can be written casually < br / >
 */
public class SHA1Util {
    public static final String SHA1 = "SHA1";
    public static final String HmacSHA1 = "HmacSHA1";
    public static final String charset = null; // Coding format; Default null is GBK

    private static SHA1Util instance;

    private SHA1Util() {
    }

    // Single case
    public static SHA1Util getInstance() {
        if (instance == null) {
            synchronized (SHA1Util.class) {
                if (instance == null) {
                    instance = new SHA1Util();
                }
            }
        }
        return instance;
    }

    /**
     * Encryption using SHA1 method (no password)
     */
    public String encode(String res) {
        try {
            MessageDigest md = MessageDigest.getInstance(SHA1);
            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Use SHA1 method for encryption (password can be set)
     */
    public String encode(String res, String key) {
        try {
            SecretKey sk = null;
            if (key == null) {
                KeyGenerator kg = KeyGenerator.getInstance(HmacSHA1);
                sk = kg.generateKey();
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                sk = new SecretKeySpec(keyBytes, HmacSHA1);
            }
            Mac mac = Mac.getInstance(HmacSHA1);
            mac.init(sk);
            byte[] result = mac.doFinal(res.getBytes());
            return BASE64Util.getInstance().encode(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

digital signature

1. Perform md5 and other summary operations on the specified value of the message to obtain the message summary. 2. Use the sender's private key to encrypt the message digest (not the message itself) 3 The receiver uses the sender's public key to decrypt and calculate the hash value. To determine whether the messages are consistent. Note: if the parameter is intercepted, the message itself will still be seen.

Mixed use (asymmetric encryption + digital signature)

First, both the receiver and the sender have a pair of secret keys. Sender: 1 Perform md5 and other summary operations on the message to obtain the message summary. 2. Use the sender's private key to encrypt the message digest. This process is also called signature. (ensuring that the receiver can confirm its identity) Encrypt the message with the receiver's public key (ensuring that the message can only be decrypted by the desired receiver) 4 Send message and message summary receiver: 1 Decrypt the message digest using the sent public key (confirm who sent the message) to obtain the original message digest 2 Decrypt the message with your own private key (get the message content safely) 3 Hash the message to obtain the local message summary. 4. Compare the original message summary with the local message summary (signature verification) to confirm whether the message has been tampered with.

Disadvantages: time consuming.