Java symmetric and asymmetric encryption and decryption (AES and RSA)

Anticipate all the cruel possibilities as much as you can, because reality will never give you warning, and it is stingy with mercy. ——Tomihiro Yoshihiro

 Today we will discuss the secret key


1. Brief introduction of symmetric encryption technology and asymmetric encryption technology

 Encryption technology can be divided into two types: symmetric and asymmetric.

Symmetric encryption and decryption use the same secret key for encryption and decryption . Commonly used symmetric encryption techniques include DES , AES, etc.

The encryption and decryption of asymmetric technology use different secret keys, the commonly used asymmetric encryption technology is RSA and so on.

2. A brief description of the use scenarios of symmetric encryption technology and asymmetric encryption technology

Why do we need asymmetric encryption and decryption technology?

Assume such a scenario that A wants to send a message to B, but does not want to send it in plain text, so the message needs to be encrypted. If symmetric encryption technology is used, the same key is used for encryption and decryption, unless B knows A's secret key in advance and keeps it well, so that the message sent by A can be decrypted.

Since the symmetric technology has only one secret key, the management of the secret key is a very troublesome problem. The birth of the asymmetric technology solves this problem. Asymmetric encryption and decryption use different secret keys, and the secret key pairs are one-to-one correspondence, that is, the ciphertext encrypted with A’s private key can only be decrypted with A’s public key.

In this case, everyone has two secret keys, a private key and a public key. The private key is known only to oneself and cannot be shared with others, while the public key is public and everyone can know it. In this way, when A wants to send a message to B, he only needs to encrypt the message with B's public key. Since only B owns B's private key, only B can decrypt the message encrypted by A with B's public key. And it is also very convenient when B wants to change his secret, he only needs to tell everyone the public key.

So, since asymmetric encryption is so good, is there no need for symmetric encryption? In fact, otherwise, because the overhead of asymmetric encryption algorithm is very high, the efficiency of sending messages encrypted directly with asymmetric technology will be very poor. So what to do? The solution is also very simple, which is to combine symmetric encryption technology with asymmetric encryption technology.

Still this example:

The first scenario (public key encryption): A wants to send a message to B.

Step 1: Mr. A generates a symmetric key, which can be randomly generated;

Step 2: A encrypts the symmetric key generated in the first step with B's public key; (generate public key and private key in advance)

Step 3: A sends the encrypted symmetric key to B; (Aes key is sent to B)

Step 4: A uses the symmetric key generated in the first step to encrypt the actual message to be sent (encrypted with aes)

Step 5: A sends the message encrypted with the symmetric key to B (the encrypted content is sent to B)

for B

He first receives the symmetric key from A, which is encrypted with B's public key, so B needs to use his own private key to decrypt the key.

Then B receives the ciphertext sent by A, and at this time uses the decrypted key to decrypt the ciphertext

This whole process ensures both safety and efficiency.

The second scenario (private key encryption): B wants to send a message to A.

Step 1: Mr. B generates a symmetric key, which can be randomly generated;

Step 2: B encrypts the symmetric key generated in the first step with its own private key;

Step 3: B sends the encrypted symmetric key to A;

Step 4: B uses the symmetric key generated in the first step to encrypt the actual message to be sent

Step 5: B sends the message encrypted with the symmetric key to A

for A

He first receives the symmetric key from B, which is encrypted with B's private key, so A needs to use B's public key to decrypt the key.

Then A receives the ciphertext sent by B, and at this time uses the decrypted key to decrypt the ciphertext

This whole process ensures both safety and efficiency.

3. The Java implementation uses AES symmetric encryption and RSA asymmetric encryption

Next is the Java implementation:

My Java implementation uses the symmetric encryption of AES and the asymmetric encryption of RSA (the symmetric encryption implementation method of DES is the same as that of AES, but because the DES algorithm itself has defects and is easy to be cracked, so now the upgraded version of AES symmetric encryption is often used)

AES encryption tool class package

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
 
/**
 * 〈Function overview〉<br>
 *
 * @className: AESUtil
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 16:41
 */
public class AESUtil {
    /**
     *
     * home.php?mod=space&uid=952169 str 加密前数据
     * @param key 对称密钥,必须为16位
     * home.php?mod=space&uid=155549 返回加密后数据
     */
    public static String encrypt(String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.encryptBase64(str);
    }
 
    /**
     *
     * @param str 加密后的数据
     * @param key 盐,必须为16位
     * @return 返回解密后数据
     */
    public static String decrypt (String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.decryptStr(str);
    }
}

RSA encryption tool class package

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import org.apache.commons.codec.binary.Base64;
import java.security.KeyPair;
 
/**
 * 〈Function overview〉<br>
 *
 * @className: RSA
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 15:02
 */
public class RSAUtil {
    private String publicKey;
    private String privateKey;
 
    /*有参构造方法,加解密时使用。公钥加密需用私钥解密,私钥加密需用公钥解密*/
    public RSAUtil(String publicKey,String privateKey){
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }
 
    /*无参构造方法,新建密钥对时使用*/
    public RSAUtil(){
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        publicKey = new String(Base64.encodeBase64(pair.getPublic().getEncoded()));
        privateKey= new String(Base64.encodeBase64((pair.getPrivate().getEncoded())));
    }
 
    /**
     *
     * @param str 加密前数据
     * @return 返回加密后数据
     */
    public String encrypt(String str){
        return SecureUtil.rsa(privateKey,publicKey).encryptBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }
 
    /**
     *
     * @param str 加密后的数据
     * @return 返回解密后数据
     */
    public String decrypt (String str){
        return SecureUtil.rsa(privateKey,publicKey).decryptStrFromBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }
 
    public String getPublicKey() {
        return publicKey;
    }
    public String getPrivateKey() {
        return privateKey;
    }
}

test class

import cn.hutool.core.util.RandomUtil;
import org.junit.Test;

/**
 * 加解密测试类
 * @author: song rose roy nba
 */
public class SerialUtilTest {
    /**
     * 测试方法
     * 使用公钥加密就必须使用私钥解密,使用私钥加密就必须使用公钥解密
     * 以下测试方式编写了私钥加密公钥解密,公钥加密私钥解密两种情况
     * 真实的业务场景一方持有私钥,一方持有公钥。因此不会存在两种密钥在一个线程里加解密的情况
     * 真实场景应该是加密方式一和解密方式二为一方,加密方式二和解密方式一为一方
     */
    @Test
    public void start(){
        /*获取aes对称密钥*/
        String aesKey = getRandomKey();
        System.out.println("我是aes对称密钥,请将我保存:"+aesKey);
        
        /*使用aes密钥对内容进行加密*/
        String content = AESUtil.encrypt("我是一封信,请将我加密后发送",aesKey);
        System.out.println("我是加密后的内容:"+content);
        
        /*生成rsa密钥对*/
        RSAUtil rsa = new RSAUtil();
        System.out.println("我是rsa公钥,请将我保存:"+rsa.getPublicKey());
        System.out.println("我是rsa私钥,请将我保存:"+rsa.getPrivateKey());
        
        /*rsa加密方式一 公钥加密,在第一个参数放入生成的公钥*/
        RSAUtil rsaUtil1 = new RSAUtil(rsa.getPublicKey(),null);
        String enContent1 = rsaUtil1.encrypt(aesKey);
        System.out.println("我是经过rsa公钥加密后的aes对称密钥,请将我保存:"+enContent1);
        
        /*rsa加密方式二 私钥加密,在第二个参数放入生成的私钥*/
        RSAUtil rsaUtil2 = new RSAUtil(null,rsa.getPrivateKey());
        String enContent2 = rsaUtil2.encrypt(aesKey);
        System.out.println("我是经过rsa私钥加密后的aes对称密钥,请将我保存:"+enContent2);
        
        /*解密方式一 私钥解密*/
        String deContent1 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa私钥解密后的aes对称密钥,请将我保存:"+deContent1);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent1));
        
        /*解密方式二 公钥解密*/
        String deContent2 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa公钥解密后的aes对称密钥,请将我保存:"+deContent2);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent2));

    }
    /**
     * 随机生成aes的秘钥
     */
    private String getRandomKey() {
        return RandomUtil.randomString(16);
    }
}

Guess you like

Origin blog.csdn.net/s_sos0/article/details/131484986