Cryptography [java] An initial exploration of symmetric encryption in encryption methods

A common encryption method

insert image description here

two symmetric encryption

  • Symmetric encryption: using the encryption method of a single-key cryptosystem, the same key can be used for both encryption and decryption of information
  • Example: Now there is an original text 3 to be sent to B
    • Set the key to 108, 3 * 108 = 324, send 324 as ciphertext to B
    • After B gets the ciphertext 324, use 324/108 = 3 to get the original text
  • Common Encryption Algorithms
    • DES : Data Encryption Standard, which is a data encryption standard , is a block algorithm that uses key encryption. It was determined as a Federal Data Processing Standard (FIPS) by the National Bureau of Standards of the US federal government in 1977 and authorized in unclassified government communications. After that, the algorithm was widely spread internationally.
    • AES : Advanced Encryption Standard, also known as Rijndael encryption in cryptography, is a block encryption standard adopted by the US federal government. This standard is used to replace the original DES, has been analyzed by many parties and is widely used all over the world.

  • features
    • Encryption speed is fast and can encrypt large files
    • The ciphertext is reversible, once the key file is leaked, it will lead to data exposure
    • After encryption, the corresponding character cannot be found in the code table, and garbled characters appear
    • Generally used in conjunction with Base64

2.1 Cipher Class Introduction

  • This class provides functionality to encrypt and decrypt encrypted passwords. It forms the core of the Java Cryptography Extension (JCE) framework.
  • To create a Cipher object, an application calls Cipher's getInstance method, passing it the name of the requested transformation . Optionally specify the name of the provider.
  • A transformation is a string describing an operation (or set of operations) to be performed on a given input, in order to produce some output. The transformation consists of **: the name of the encryption algorithm (for example, DES ), and may be followed by a feedback mode and a padding scheme. **
  • The conversion form is as follows:
- “ 算法/模式/填充 ”或“ 算法 ”  
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
- 在该一种情况下,使用模式和填充方案的提供者特定的默认值
Cipher c = Cipher.getInstance("DES"); 

2.2 Base Algorithm

  • Base64: 64 characters are used in the encoding process: uppercase A to Z, lowercase a to z, numbers 0 to 9, "+" and "/"
  • Base64 is one of the most common readable encoding algorithms for transmitting 8Bit bytecodes on the network
  • The readability encoding algorithm is not for the security of the data, but for readability . Readability coding does not change the content of the information, only the form of expression of the content of the information
  • Base58 is an encoding method used in Bitcoin (Bitcoin), which is mainly used to generate Bitcoin wallet addresses. Compared with Base64, Base58 does not use the number "0", the uppercase "O", the uppercase "I", and the lowercase "i", as well as the "+" and "/" symbols.

  • Base64 algorithm principle
  • base64 is a group of 3 bytes, a byte of 8 bits, a total of 24 bits, and then convert the 3 bytes into 4 groups of 6 bits, 3 ∗ 8 = 4 ∗ 6 = 24 3 * 8 = 4 * 6 = 2438=46=24 , each group has 6 bits, and the missing 2 bits will be filled with 0 in the high bit. The advantage of this is that the base takes the last 6 bits, remove the high 2 bits, then the value of base64 can be controlled within 0-63 bit, so it is called base64, 111 111 = 32 + 16 + 8 + 4 + 2 + 1 =64.
  • Base64 is a group of three bytes. If we have insufficient digits, we will use an equal sign to fill them up
    insert image description here

2.3 Supplement: Byte&bit

  • Byte: byte. The basic unit of data storage, such as a mobile hard disk 1T, the unit is byte
  • bit : bit/bit.. Either 0 or 1. The unit of data transmission. For example, the broadband at home is 100Mb, and the download speed does not reach 100MB. Generally, it is 12-13MB, so it is because 100 / 8 MB is needed
  • Relationship: 1Byte = 8bit

  • demo
    public class ByteBit {
          
          
        public static void main(String[] args) {
          
          
            String a = "a";
            byte[] bytes = a.getBytes();
            for (byte aByte : bytes) {
          
          
                int c = aByte;
                System.out.println(c);
                // byte 字节,对应的bit是多少
                String s = Integer.toBinaryString(c);
                System.out.println(s);
            }
        }
    }
    
      ![在这里插入图片描述](https://img-blog.csdnimg.cn/2e86e1293f5b4216bc0fe5c4cf3736fa.png)
    

  • The byte corresponding to an English letter
public static void main(String[] args) throws Exception{
    
    
        String a = "A";
        byte[] bytes = a.getBytes();
        for (byte aByte : bytes) {
    
    
            System.out.println(aByte);
            String s = Integer.toBinaryString(aByte);
            System.out.println(s);
        }
    }

  • In the utf-8 encoding format, one Chinese corresponds to three bytes
  • In the GBK encoding format, one Chinese corresponds to two bytes
public static void main(String[] args) throws Exception{
    
    
        String a = "天";
        byte[] bytes = a.getBytes();
        for (byte aByte : bytes) {
    
    
            System.out.println(aByte);
            String s = Integer.toBinaryString(aByte);
            System.out.println(s);
        }
    }

insert image description here

public static void main(String[] args) throws Exception{
    
    
        String a = "天";
        byte[] bytes = a.getBytes("GBK");
        for (byte aByte : bytes) {
    
    
            System.out.println(aByte);
            String s = Integer.toBinaryString(aByte);
            System.out.println(s);
        }
    }

insert image description here

2.4 DES Encryption Demonstration

public static void main(String[] args) throws Exception{
    
    
        // 原文
        String input = "天下";
        // des加密必须是8位
        String key = "12345678";
        // 算法
        String algorithm = "DES";

        String transformation = "DES";
        
        // Cipher:密码,获取加密对象
        // transformation:表示使用什么类型加密
        Cipher cipher = Cipher.getInstance(transformation);
        /*	第一步:指定秘钥规则
         		第一个参数表示:密钥,key的字节数组
         		第二个参数表示:算法
        */
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        /* 
         第二步:对加密进行初始化
         	第一个参数:表示模式,有加密模式和解密模式
         	第二个参数:表示秘钥规则
        */
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 第三步:进行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        
        // 打印密文,因为ascii码有负数,解析不出来,所以乱码
        System.out.println(new String(bytes));
        //
    }
  • Note: The DES encryption algorithm stipulates that the key must be eight bytes, otherwise the following error will occur
java.security.InvalidKeyException: Wrong key size

	at java.base/com.sun.crypto.provider.DESCrypt.init(DESCrypt.java:536)
	at java.base/com.sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.java:97)
	at java.base/com.sun.crypto.provider.CipherCore.init(CipherCore.java:481)
	at java.base/com.sun.crypto.provider.CipherCore.init(CipherCore.java:399)
	at java.base/com.sun.crypto.provider.DESCipher.engineInit(DESCipher.java:187)
	at java.base/javax.crypto.Cipher.implInit(Cipher.java:869)
	at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:931)
	at java.base/javax.crypto.Cipher.init(Cipher.java:1301)
	at java.base/javax.crypto.Cipher.init(Cipher.java:1238)
	at DESTest.test1(DESTest.java:31)
  • Note: Garbled characters appear because the corresponding byte has a negative number, but the negative number does not appear in the ascii code table, so there are garbled characters, which need to be transcoded with base64
    insert image description here
    • Note: The imported package isorg.apache.commons.codec.binary.Base64;
    import org.apache.commons.codec.binary.Base64;
    //对数据进行Base64编码
     String s = Base64.encodeBase64String(bytes);
     System.out.println(s);
    

insert image description here

2.5 DES decryption


import org.junit.Test;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DESTest {
    
    
    @Test
    public  void test() throws Exception {
    
    
        String input ="天下";
        // DES加密算法,key的大小必须是8个字节
        String key = "12345678";

        String transformation = "DES";
        // 指定获取密钥的算法
        String algorithm = "DES";
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);

        String s = decryptDES(encryptDES, key, transformation, algorithm);
        System.out.println("解密:" + s);

    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(DES,密钥的长度必须是8个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
    
        // 获取加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
        // 第一个参数key的字节
        // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // ENCRYPT_MODE:加密模式
        // 初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());

        // 输出加密后的数据
        String encode = Base64.encodeBase64String(bytes);

        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密钥
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @throws Exception
     * @return: 原文
     */
    private static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
    
        // 1,获取Cipher对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // DECRYPT_MODE: 解密模式
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密,上面使用的base64编码,下面直接用密文
        byte[] bytes = cipher.doFinal(Base64.decodeBase64(input));
        //  因为是明文,所以直接返回
        return new String(bytes);
    }
}

insert image description here

2.6 Supplement: Solution to IDEA console garbled characters

insert image description here

2.7 AES encryption and decryption

  • AES encryption and decryption are the same as DES encryption and decryption codes, only need to modify the encryption algorithm
  • The key key of AES encryption needs to pass in 16 bytes, otherwise, the following error message will appear
    java.security.InvalidKeyException: Invalid AES key length: 8 bytes
    
import org.junit.Test;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DESTest {
    
    
    @Test
    public  void test() throws Exception {
    
    
        String input ="天下";
        // DES加密算法,key的大小必须是8个字节
        String key = "12345678";

        String transformation = "AES";
        // 指定获取密钥的算法
        String algorithm = "AES";
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);

        String s = decryptDES(encryptDES, key, transformation, algorithm);
        System.out.println("解密:" + s);

    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(DES,密钥的长度必须是8个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
    
        // 获取加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
        // 第一个参数key的字节
        // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // ENCRYPT_MODE:加密模式
        // 初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());

        // 输出加密后的数据
        String encode = Base64.encodeBase64String(bytes);

        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密钥
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @throws Exception
     * @return: 原文
     */
    private static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
    
        // 1,获取Cipher对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // DECRYPT_MODE: 解密模式
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密,上面使用的base64编码,下面直接用密文
        byte[] bytes = cipher.doFinal(Base64.decodeBase64(input));
        //  因为是明文,所以直接返回
        return new String(bytes);
    }
}

insert image description here

2.8 Supplement: The usage difference between toString() and new String()

public static void main(String[] args) {
    
    
        // 表示密文
        String str="TU0jV0xBTiNVYys5bEdiUjZlNU45aHJ0bTdDQStBPT0jNjQ2NDY1Njk4IzM5OTkwMDAwMzAwMA==";
        // 使用base64进行解码
        String rlt1=new String(Base64.decodeBase64(str.getBytes()));
        // 使用base64进行解码
        String rlt2= Base64.decodeBase64(str).toString();

        System.out.println("new String===" + rlt1);

        System.out.println("toString==" + rlt2);

    }

insert image description here

  • Which one is correct? Why?

  • The new String() method, because Base64 encryption and decryption is a principle of converting the encoding format

  • The usage difference between toString() and new String()

  • str.toString is to call the toString method of the class of this object object. Usually returns such aString:[class name]@[hashCode]

  • new String(str) is based on the fact that the parameter is a byte array, using the default encoding format of the java virtual machine, to decode this byte array into corresponding characters. If the default encoding format of the virtual machine is ISO-8859-1, the character corresponding to the byte can be obtained according to the ascii encoding table.

  • When to use the two methods:

  • When new String() generally uses character transcoding, when byte[] array

  • toString() object is used when printing

2.9 Encryption mode

2.9.1 ECB

  • ECB : Electronic codebook, electronic code book. The message to be encrypted is divided into several blocks according to the block size of the block cipher, and each block is independently encrypted
    insert image description here
  • Pros: Can process data in parallel
  • Disadvantages: The same original text generates the same ciphertext, which cannot protect data well
  • Simultaneous encryption, the original text is the same, and the encrypted cipher text is also the same

2.9.2 CBC

  • CBC : Cipher-block chaining, cipher block chaining. Each plaintext block is XORed with the previous ciphertext block before being encrypted. In this approach, each ciphertext block depends on all preceding plaintext blocks
    insert image description here
  • Advantages: The ciphertext generated by the same original text is different
  • Cons: Process data serially.

2.10 Fill Mode

  • When the data that needs to be processed in blocks, and the data length does not meet the block processing requirements, fill the block length rules according to a certain method

2.10.1 NoPadding

  • not filled
  • Under the DES encryption algorithm, the length of the original text must be an integer multiple of 8 bytes
  • Under the AES encryption algorithm, the length of the original text must be an integer multiple of 16 bytes

2.10.2 PKCS5Padding

  • The size of the data block is 8 bits, make up if it is not enough

2.10.3 Tips

  • By default, the encryption mode and padding mode are: ECB/PKCS5Padding

  • If you use CBC mode, you need to add parameters when initializing the Cipher object, the initialization vector IV:IvParameterSpec iv = new IvParameterSpec(key.getBytes());

  • encryption mode and padding mode

    AES/CBC/NoPadding (128)
    AES/CBC/PKCS5Padding (128)
    AES/ECB/NoPadding (128)
    AES/ECB/PKCS5Padding (128)
    DES/CBC/NoPadding (56)
    DES/CBC/PKCS5Padding (56)
    DES/ECB/NoPadding (56)
    DES/ECB/PKCS5Padding (56)
    DESede/CBC/NoPadding (168)
    DESede/CBC/PKCS5Padding (168)
    DESede/ECB/NoPadding (168)
    DESede/ECB/PKCS5Padding (168)
    RSA/ECB/PKCS1Padding (1024, 2048)
    RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
    RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
    

2.11 Demonstration of encryption mode and padding mode

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public static void main(String[] args) throws Exception{
    
    
        // 原文 如果使用的是不填充的模式,那么原文必须是8个字节的整数倍
        String input = "天下";
        // 定义key
        // 如果使用des进行加密,那么密钥必须是8个字节
        String key = "12345678";
        // ECB:表示加密模式
        // PKCS5Padding:表示填充模式 qANksk5lvqM=
        // 如果默认情况,没有写填充模式和加密模式,那么默认就使用DES/ECB/PKCS5Padding
        String transformation = "DES/CBC/PKCS5Padding";
        // 加密类型
        String algorithm = "DES";
        // 指定获取密钥的算法
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);

        String s = decryptDES(encryptDES, key, transformation, algorithm);
        System.out.println("解密:" + s);
    }

    /**
     * 解密
     * @param encryptDES  密文
     * @param key         密钥
     * @param transformation 加密算法
     * @param algorithm   加密类型
     * @return
     */
    private static String decryptDES(String encryptDES, String key, String transformation, String algorithm) throws Exception{
    
    
        Cipher cipher = Cipher.getInstance(transformation);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
        // 创建iv向量
        IvParameterSpec iv = new IvParameterSpec(key.getBytes());
        //Cipher.DECRYPT_MODE:表示解密
        // 解密规则
        cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,iv);
        // 解密,传入密文
        byte[] bytes = cipher.doFinal(Base64.decodeBase64(encryptDES));

        return new String(bytes);
    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(DES,密钥的长度必须是8个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
    
        // 获取加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
        // 第一个参数key的字节
        // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // 创建iv向量,iv向量,是使用到CBC加密模式
        // 在使用iv向量进行加密的时候,iv的字节也必须是8个字节
        IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());
        // ENCRYPT_MODE:加密模式
        // DECRYPT_MODE: 解密模式
        // 初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE,sks,iv);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());

        // 输出加密后的数据
        String encode = Base64.encodeBase64String(bytes);

        return encode;
    }

insert image description here

Guess you like

Origin blog.csdn.net/yang2330648064/article/details/130467246