Cifrado y descifrado simétrico y asimétrico de Java (AES y RSA)

Anticipa todas las posibilidades crueles tanto como puedas, porque la realidad nunca te avisará y es tacaña con la misericordia. ——Tomihiro Yoshihiro

 Hoy hablaremos de la clave secreta.


1. Breve introducción de la tecnología de cifrado simétrico y la tecnología de cifrado asimétrico

 La tecnología de cifrado se puede dividir en dos tipos: simétrica y asimétrica.

El cifrado y descifrado simétrico utilizan la misma clave secreta para el cifrado y el descifrado . Las técnicas de cifrado simétrico comúnmente utilizadas incluyen DES , AES, etc.

El cifrado y descifrado de la tecnología asimétrica utiliza diferentes claves secretas, la tecnología de cifrado asimétrico comúnmente utilizada es RSA, etc.

2. Una breve descripción de los escenarios de uso de la tecnología de cifrado simétrico y la tecnología de cifrado asimétrico

¿Por qué necesitamos tecnología de cifrado y descifrado asimétrico?

Suponga que A quiere enviar un mensaje a B, pero no quiere enviarlo en texto sin formato, por lo que el mensaje debe cifrarse. Si se utiliza la tecnología de cifrado simétrico, se utiliza la misma clave secreta para el cifrado y el descifrado, a menos que B conozca la clave secreta de A de antemano y la conserve bien, de modo que el mensaje enviado por A pueda descifrarse.

Dado que la tecnología simétrica tiene solo una clave secreta, la gestión de la clave secreta es un problema muy problemático. El nacimiento de la tecnología asimétrica resuelve este problema. El cifrado y descifrado asimétrico utilizan diferentes claves secretas, y los pares de claves secretas tienen una correspondencia uno a uno, es decir, el texto cifrado cifrado con la clave privada de A solo se puede descifrar con la clave pública de A.

En este caso, cada persona tiene dos claves secretas, una clave privada y una clave pública, la clave privada solo la conoce uno mismo y no se puede compartir con otros, mientras que la clave pública es pública y todos pueden conocerla. De esta forma, cuando A quiere enviar un mensaje a B, solo necesita cifrar el mensaje con la clave pública de B. Dado que solo B posee la clave privada de B, solo B puede descifrar el mensaje cifrado por A con la clave pública de B. Y también es muy conveniente cuando B quiere cambiar su secreto, solo necesita decirles a todos la clave pública.

Entonces, dado que el cifrado asimétrico es tan bueno, ¿no hay necesidad de cifrado simétrico? De hecho, no es el caso, porque la sobrecarga del algoritmo de cifrado asimétrico es muy alta, por lo que la eficiencia de enviar mensajes cifrados directamente con tecnología asimétrica será muy pobre. ¿Entonces lo que hay que hacer? La solución también es muy simple, que consiste en combinar la tecnología de cifrado simétrico con la tecnología de cifrado asimétrico.

Todavía este ejemplo:

El primer escenario (cifrado de clave pública): A quiere enviar un mensaje a B.

Paso 1: Mr. A genera una clave simétrica, que puede generarse aleatoriamente;

Paso 2: A cifra la clave simétrica generada en el primer paso con la clave pública de B; (generar clave pública y clave privada por adelantado)

Paso 3: A envía la clave simétrica cifrada a B; (la clave Aes se envía a B)

Paso 4: A usa la clave simétrica generada en el primer paso para cifrar el mensaje real que se enviará (cifrado con aes)

Paso 5: A envía el mensaje cifrado con la clave simétrica a B (el contenido cifrado se envía a B)

para B

Primero recibe la clave simétrica de A, que está cifrada con la clave pública de B, por lo que B necesita usar su propia clave privada para descifrar la clave.

Luego, B recibe el texto cifrado enviado por A y, en este momento, usa la clave descifrada para descifrar el texto cifrado.

Todo este proceso garantiza tanto la seguridad como la eficiencia.

El segundo escenario (cifrado de clave privada): B quiere enviar un mensaje a A.

Paso 1: Mr. B genera una clave simétrica, que puede generarse aleatoriamente;

Paso 2: B cifra la clave simétrica generada en el primer paso con su propia clave privada;

Paso 3: B envía la clave simétrica cifrada a A;

Paso 4: B utiliza la clave simétrica generada en el primer paso para cifrar el mensaje real que se enviará

Paso 5: B envía el mensaje encriptado con la clave simétrica a A

para

Primero recibe la clave simétrica de B, que está cifrada con la clave privada de B, por lo que A necesita usar la clave pública de B para descifrar la clave.

Luego, A recibe el texto cifrado enviado por B y, en este momento, usa la clave descifrada para descifrar el texto cifrado.

Todo este proceso garantiza tanto la seguridad como la eficiencia.

3. La implementación de Java utiliza cifrado simétrico AES y cifrado asimétrico RSA

La siguiente es la implementación de Java:

Mi implementación de Java usa el cifrado simétrico de AES y el cifrado asimétrico de RSA (el método de implementación de cifrado simétrico de DES es el mismo que el de AES, pero debido a que el algoritmo DES en sí tiene defectos y es fácil de descifrar, ahora se usa a menudo la versión mejorada del cifrado simétrico AES)

Paquete de clase de herramienta de cifrado AES

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);
    }
}

Paquete de clase de herramienta de cifrado RSA

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;
    }
}

clase de prueba

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);
    }
}

Supongo que te gusta

Origin blog.csdn.net/s_sos0/article/details/131484986
Recomendado
Clasificación