preface

There are two methods to encrypt data: shared key encryption, in which the same key is used for encryption and decryption, and public key encryption, in which different keys are used for encryption and decryption.

This article will explain the two encryption mechanisms and related issues in the form of pictures and texts, and select the most widely used two encryption algorithms to be implemented in JAVA. Welcome interested developers to read this article.

Shared key encryption

concept

Shared key encryption is an encryption mode in which encryption and decryption use the same key. Because the same key is used, this algorithm is also called symmetric encryption. The shared encryption algorithms are as follows:AES,DES,Dynamic passwordAES is the most widely used.

Process diagram

For example, A is going to send data to B over the InternetBecause of the risk of eavesdropping, data needs to be encrypted before being sent.

  • User A uses the key to encrypt data and sends the secret message to user B.

  • B Uses the same key to decrypt the received secret message. So B gets the original data. At this point, the data is already encrypted, and there is no need to worry about third parties stealing the data, because it has no key to unlock the ciphertext.

Possible problems

As shown in the figure, when B receives the ciphertext sent by A, X may have eavesdropped on the ciphertext.


  • In this case, USER B does not know what key is used for encryption.
  • A needs to somehow give the key to B. Like ciphertext, A sends A key to B over the Internet.
  • User B uses the received key to decrypt the ciphertext. However, the key may be eavesdropped by X. In this case, X can also decrypt the ciphertext with the key.

When using shared key encryption, if the receiver does not know what the key is, the sender needs to send the key to the receiver over the Internet. In this case, the key may be monitored by a third party. This is the biggest problem of shared key encryption.

The solution

As mentioned above, shared key encryption has key delivery problem. To solve this problem, we can use “key exchange protocol” and “public key encryption” two methods.

The Enigma cipher machine

Used during world war ii, the German enigma machine “” the encryption method used is the Shared secret key encryption, known as British mathematician Alan Turing” cracked machine generated code for the ciphertext, did a lot of contribution for the British in world war ii, such as the famous “d-day” event, the imitation game, watching a movie last night The film tells the story of Turing’s life, including the part of the enigma code machine, a good film, interested friends can go to see.

JAVA implements AES encryption

We use Java to achieve AES encryption.

  • Create an AESUtils file and write an AES encryption utility class
package com.lk.util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;

public class AESUtils {
    Key length: 128, 192 or 256 */
    private static final int KEY_SIZE = 128;

    /** * Encryption/decryption algorithm name */
    private static final String ALGORITHM = "AES";

    /** * Random number generator algorithm name */
    private static final String RNG_ALGORITHM = "SHA1PRNG";
 /** * Generate key object *@paramKey byte[] Type parameter *@returnAES key object */ private static SecretKey generateKey(byte[] key) throws Exception { // Create a secure random number generator SecureRandom random = SecureRandom.getInstance(RNG_ALGORITHM); // Sets the byte array of the key as the seed of the secure random number generator random.setSeed(key);  // Create the AES algorithm generator KeyGenerator gen = KeyGenerator.getInstance(ALGORITHM); // Initialize the algorithm generator gen.init(KEY_SIZE, random);  // Generate AES key objects return gen.generateKey(); }  /** * Data encryption: plaintext -> ciphertext */ public static byte[] encrypt(byte[] plainBytes, byte[] key) throws Exception { // Generate a key object SecretKey secKey = generateKey(key);  // Get the AES cipher Cipher cipher = Cipher.getInstance(ALGORITHM); // Initialize the cipher (encryption model) cipher.init(Cipher.ENCRYPT_MODE, secKey);  // Encrypt data and return ciphertext  return cipher.doFinal(plainBytes); }  /** * Data decryption: ciphertext -> plaintext */ public static byte[] decrypt(byte[] cipherBytes, byte[] key) throws Exception { // Generate a key object SecretKey secKey = generateKey(key);  // Get the AES cipher Cipher cipher = Cipher.getInstance(ALGORITHM); // Initialize the cipher (decryption model) cipher.init(Cipher.DECRYPT_MODE, secKey);  // Decrypt data and return clear text return cipher.doFinal(cipherBytes); }  /** * byte array to hexadecimal **@paramBytes Byte array *@returnReturns the hexadecimal string */ public static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte aByte : bytes) { String hex = Integer.toHexString(aByte & 0xFF); if (hex.length() < 2) { sb.append(0); } sb.append(hex); } return sb.toString(); }  /** * hexadecimal to byte *@paramInHex Hexadecimal character string *@return byte */ public static byte hexToByte(String inHex) { return (byte) Integer.parseInt(inHex, 16); }  /** * Hexadecimal to byte array *@paramInHex Hexadecimal character string *@return* / byte array public static byte[] hexToByteArray(String inHex) { int hexlen = inHex.length(); byte[] result; if (hexlen % 2= =1) { / / odd hexlen++; result = new byte[(hexlen / 2)]; inHex = "0" + inHex; } else { / / even result = new byte[(hexlen / 2)]; } int j = 0; for (int i = 0; i < hexlen; i += 2) { result[j] = hexToByte(inHex.substring(i, i + 2)); j++; } return result; }  /** * Encrypt file: plaintext input -> ciphertext output */ public static void encryptFile(File plainIn, File cipherOut, byte[] key) throws Exception { aesFile(plainIn, cipherOut, key, true); }  /** * Decrypt files: ciphertext input -> plaintext output */ public static void decryptFile(File cipherIn, File plainOut, byte[] key) throws Exception { aesFile(plainOut, cipherIn, key, false); }  /** * AES encrypts/decrypts files */ private static void aesFile(File plainFile, File cipherFile, byte[] key, boolean isEncrypt) throws Exception { // Get the AES cipher Cipher cipher = Cipher.getInstance(ALGORITHM); // Generate a key object SecretKey secKey = generateKey(key); // Initializes the password cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secKey);  // Encrypt/decrypt data InputStream in = null; OutputStream out = null;  try { if (isEncrypt) { // Encryption: plaintext files are input, ciphertext files are output in = new FileInputStream(plainFile); out = new FileOutputStream(cipherFile); } else { // Decryption: ciphertext files are input, plaintext files are output in = new FileInputStream(cipherFile); out = new FileOutputStream(plainFile); }  byte[] buf = new byte[1024]; int len = -1;  // Loop read data encrypt/decrypt while((len = in.read(buf)) ! = -1) { out.write(cipher.update(buf, 0, len)); } out.write(cipher.doFinal()); // Need to wrap up  out.flush();  } finally{ close(in); close(out); }} private static void close(Closeable c) { if(c ! =null) { try { c.close(); } catch (IOException e) { // nothing}}}} Copy the code
  • Test the utility class in the main function
 public static void main(String[] args) throws Exception {
        // The content of the original text
        String content = "Hello, I'm sending data.";

        // The original password for AES encryption/decryption
        String key = "MagicalProgrammer";

        // Encrypt data and return ciphertext
        byte[] cipherBytes = AESUtils.encrypt(content.getBytes(), key.getBytes());

        // byte[] to hexadecimal
        String cipherString = AESUtils.bytesToHex(cipherBytes);

        // Outputs the encrypted hexadecimal ciphertext
        System.out.println("The encrypted ciphertext is:);
        System.out.println(cipherString);
 // Decrypt data and return clear text byte[] plainBytes = AESUtils.decrypt(AESUtils.hexToByteArray(cipherString), key.getBytes());  // Output the decrypted plaintext System.out.println("Decrypted result:"); System.out.println(new String(plainBytes)); } Copy the code

Public-key encryption

concept

Public-key encryption is an encryption method in which encryption and decryption use different keys. This algorithm is also known as “asymmetric encryption” because of the different keys used. The encryption key is called a “public key” and the decryption key is called a “private key”.

Process diagram

As is shown in the picture, A sends data to B over the Internet.

  • First, the public and private keys are generated by receiver B.
  • The public key is then sent to B.
  • User A uses the public key sent by user B to encrypt data
  • User A sends the ciphertext to user B. User B decrypts the ciphertext using the private key. So, B gets the original data.
  • Both the public key and the ciphertext are transmitted over the Internet and can therefore be eavesdropped by X. However, the ciphertext cannot be decrypted using the public key, so X cannot get the original data.

Public key encryption algorithms include RSA algorithm and Elliptic curve encryption algorithm, among which RSA algorithm is the most widely used.

Convenient data transmission for multiple people

Using public key encryption is convenient when transmitting data with multiple people.

For example, B pre-prepares public and private keys,

The public key is not afraid of being known, so B can publish the public key on the Internet.At this point, a lot of people want to send data to B.

  • First, the person who wants to send the data needs to obtain the public key issued by B from Wang Shan.
  • The obtained public key is then used to encrypt the data to be sent.
  • Finally, the ciphertext is sent to B
  • B decrypts the received ciphertext with the private key to obtain the original data. In this case, there is no need to prepare a key for each sending object. Private keys that need to be kept secret are held by the recipient, so security is also higher.

If the shared key is used for encryption, the number of required keys increases rapidly as the number of sender users increases. For example, if you have two people sending data to each other, you need two keys, but if you have five people sending data to each other, you need 10 keys, and 100 people need 4,950 keys. Assuming that n people need to send data to each other, the number of keys required is n(n-1)/2.

Man-in-the-middle attack

Public-key encryption, the reliability of the public key problems when B send A public key, the public key may be intercepted by A third party, the third party to get the public key, save to A local, oneself to generate A new public key is sent to A, A, using A third party’s public key to encrypt data, send data to A, Hijacked by A third party to send data, with its own private key to decrypt the data, the third party will get the B to send data, then use third party B’s public key to decrypt data encrypted again, then sent to B, B with your own private key to normal solved B sends data, the whole process of sending and receiving, without any problems, Therefore, A cannot detect that the data has been leaked. This method of eavesdropping on data by replacing the public key midway is called “man-in-the-middle attack”.

Let’s go back to when B generated the public key and the private key. We use PB for the public key and SB for the private key.

X wants to eavesdrop on the data A sends to B, so he prepares the public key PX and the private key SX.

  • When B sends the public key PB to A
  • X replaces the public key PB with its own PX
  • The public key Px is then passed to A. Since the public key cannot show who generated it, A does not notice that the public key she received has been replaced.
  • A encrypts data using the public key PX
  • After USER A sends the ciphertext to user B, X receives the ciphertext.
  • The ciphertext is encrypted by the public key PX generated by X, so X can use its private key SX to decrypt the ciphertext.
  • X encrypts data with the public key PB generated by B
  • X sends the ciphertext to B, which is encrypted by the public key PB sent by B. Therefore, B can decrypt the ciphertext with its private key SB. There is no problem from receiving the ciphertext to decrypting the ciphertext, so B cannot be aware that it has been wiretapped.

The solution

The reliability of the public key may be problematic. Therefore, A cannot determine whether the received public key is from B. To solve this problem, A digital certificate is required.

Another problem with public-key encryption is that both encryption and decryption are time-consuming. So this approach is not suitable for sending bits and pieces of data continuously. To solve this problem, “hybrid encryption” is used.

Implementation difficulties

It is not easy to find an algorithm to implement public-key encryption. Considering the computing process required for encryption, the algorithm must meet the following conditions.

  • Data can be encrypted with a certain value
  • A calculation of the encrypted data using another value can restore the data to its original state.
  • It is impossible to deduce one key from another.

A little thought shows how difficult it is to find an algorithm that meets these criteria. Therefore, RSA and other algorithms that can realize public-key encryption are of great significance to the security of today’s Internet society.

JAVA implements RSA encryption

We use Java to implement RSA encryption

  • Create RSAUtils file, write RSA encryption tool class
package com.lk.util;

import java.util.Base64;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/** * RSA encryption tool class */
public class RSAUtils {
    /** * The key length corresponds to the original length and the longer the key length, the slower the key speed */
    private final static int KEY_SIZE = 1024;
    /** * encapsulates randomly generated public and private keys */
    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();

    /** * Randomly generates a key pair */
    public static Map genKeyPair(a) throws NoSuchAlgorithmException {
        The KeyPairGenerator class is used to generate public and private key pairs based on the RSA algorithm to generate objects
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // Initializes the key pair generator
        keyPairGen.initialize(KEY_SIZE, new SecureRandom());
        // generate a keyPair, stored in keyPair
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // get the private key
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // Get the public key
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        // Get the private key string
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        // Save the public and private keys to Map
        //0 indicates a public key
        keyMap.put(0, publicKeyString);
        //1 indicates the private key
        keyMap.put(1, privateKeyString);
        return keyMap;
    }

    /** * RSA public key encryption **@paramSTR Encryption character string *@paramPublicKey public key *@returnCipher *@throwsException Indicates the Exception information during encryption */
    public static String encrypt(String str, String publicKey) throws Exception {
        // Base64 encoded public key
        byte[] decoded = Base64.getDecoder().decode(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        / / RSA encryption
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
        return outStr;
    }
 /** * RSA private key decryption **@paramSTR Encryption character string *@paramPrivateKey private key *@returnClear *@throwsException Exception information during decryption */ public static String decrypt(String str, String privateKey) throws Exception { // 64-bit decoded encrypted string byte[] inputByte = Base64.getDecoder().decode(str); // Base64 encoded private key byte[] decoded = Base64.getDecoder().decode(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); / / RSA decryption Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); String outStr = new String(cipher.doFinal(inputByte)); returnoutStr; }} Copy the code
  • Test the utility class in the main function
public static void main(String[] args) throws Exception {
        // Randomly generated keys and public keys
        Map<Integer, String> keyMap = new HashMap<Integer, String>();
        // Generate public and private keys
        keyMap = RSAUtils.genKeyPair();
        System.out.println("Public." + keyMap.get(0));
        System.out.println("The private key." + keyMap.get(1));

        // The data to encrypt
        String message = "Hello, I'm encrypting data through RSA.";

        // Use public key encryption
        String messageEn = RSAUtils.encrypt(message, keyMap.get(0));
        System.out.println("The cipher text." + messageEn);

        // Decrypt with private key
        String messageDe = RSAUtils.decrypt(messageEn, keyMap.get(1));
        System.out.println("Decryption." + messageDe);
    }
Copy the code

Write in the last

  • The pictures used in this article are from “my first algorithm book”, if infringement, please leave a message in the comment section, the author immediately delete the relevant pictures.
  • If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
  • This article was first published in nuggets. Reprint is prohibited without permission 💌