Firma de cifrado RSA para comunicación Https

RSA (criptosistema de clave pública) se utiliza generalmente en el certificado digital de comunicación Https. Agregue algún otro conocimiento antes de aprender sobre RSA.

Criptografía de clave pública

El criptosistema de clave pública se divide en tres partes, clave pública, clave privada y algoritmo de cifrado y descifrado. Su proceso de cifrado y descifrado es el siguiente:

  1. Cifrado: Cifre el contenido (o texto explicativo) mediante un algoritmo de cifrado y clave pública para obtener el texto cifrado. La clave pública es necesaria para el proceso de cifrado.
  2. Descifrado: descifre el texto cifrado mediante el algoritmo de descifrado y la clave privada para obtener el texto sin formato. El proceso de descifrado requiere un algoritmo de descifrado y una clave privada.
    公钥密码体制的公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。两者都可以加解密数据,公钥加密的内容只能私钥解密,私钥加密的内容只能公钥解密

Algoritmos de clave simétrica

El algoritmo de cifrado simétrico significa que la clave utilizada para el cifrado y la clave utilizada para el descifrado son las mismas. Por lo tanto, si el algoritmo de cifrado simétrico es para garantizar la seguridad, la clave debe mantenerse en secreto para que solo el usuario pueda conocerla.安全系数相对较低

Algoritmos de clave asimétrica

El algoritmo de cifrado asimétrico significa que la clave utilizada para el cifrado y la clave utilizada para el descifrado son diferentes. RSA es un algoritmo de cifrado asimétrico.

Secreto

La clave, generalmente una cadena o un número, se pasa al algoritmo de cifrado / descifrado durante el cifrado o descifrado. Tanto las partes del cifrado como del descifrado pueden acordar los métodos de cifrado y descifrado por sí mismas, por lo que ha surgido una variedad de métodos de cifrado y descifrado.

Cifrado y descifrado de datos

El cifrado se refiere a convertir un determinado contenido en base64, hexadecimal y otros formatos a través de un determinado algoritmo de cifrado y clave secreta. El descifrado consiste en convertir información cifrada en información original a través de un algoritmo de descifrado específico y una clave secreta. El cifrado y descifrado de datos es para la seguridad de la transmisión de datos y evita la interceptación por parte de otros. Los algoritmos de cifrado y descifrado son generalmente cifrados simétricos y cifrados asimétricos.

Firma de datos

La firma es para agregar una pieza de contenido después de la información, lo que puede probar que la información no ha sido modificada. Esquemas de firmas generalmente utilizados:

  1. Consiste en hacer un cálculo hash sobre la información para obtener un valor hash, y luego enviar el valor hash (después del cifrado) como firma y mensaje.
  2. Después de recibir la información, el receptor recalculará el valor hash de la información y lo comparará con el valor hash adjunto a la información (después del descifrado). Si son consistentes, el contenido de la información no ha sido modificado.
    1. 这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。
    2.不同的内容一定会得到不同的hash值,hash的加解密是为了防止传输过程中被更改,造成信息是否被篡改无法准确验证。

RSA

RSA utiliza un criptosistema de clave pública. RSA es un algoritmo diseñado por tres matemáticos Rivest, Shamir y Adleman, por eso se llama RSA. Es la piedra angular de la seguridad de las comunicaciones informáticas y el algoritmo de cifrado más importante.

Este algoritmo es muy confiable, cuanto más larga es la clave, más difícil es descifrarla. Según los documentos publicados, la clave RSA más larga que se ha descifrado es de 768 bits binarios. En otras palabras, una clave de más de 768 bits no se puede descifrar (al menos nadie lo ha anunciado públicamente). Por lo tanto, se puede considerar que la clave RSA de 1024 bits es básicamente segura y la clave de 2048 bits es extremadamente segura (en la comunicación de red, generalmente es de 2048 bits ).
Para el principio del algoritmo RSA, se recomienda ver el principio del algoritmo RSA

En aplicaciones prácticas, usamos la comunicación Https como ejemplo para analizar el uso de RSA, y ahora simulamos el diálogo común entre cliente y servidor en la comunicación https:

  • cliente >> servidor: hola, este es clientA
  • servidor >> cliente: Hola, este es el servidor.
  • cliente >> servidor: demuestre que es servidor, str [str是随机字符串]
  • servidor >> cliente: str {XXX-hash} [{}中是私钥RSA加密后内容,hash为str的has,后面都如此表示]
    [client 收到str原文,计算str的hash1,通过证书中RSA公钥解密XXX-hash,获得密文中的内容与hash2,比较解密内容与原内容是否一致,解密的hash和原文计算的hash是否一致,都一致说明服务器是真的,可以进行下一步]
  • cliente >> servidor: De hecho, usted es el servidor, esta es la clave secreta del algoritmo de encriptación x {XXXX}, usemos el algoritmo de encriptación X para la comunicación en el futuro
  • servidor >> cliente: {Sí, estoy listo para la comunicación}[内容经x算法加密]
  • cliente >> servidor: {comprobar el saldo de mi cuenta}[内容经x算法加密]

**注意**
1. Después de verificar la autenticidad de las identidades de ambas partes, las dos partes pueden acordar utilizar un nuevo algoritmo de cifrado simétrico para comunicarse. Esto es relativamente gratuito y altamente expandible. Los diferentes métodos de cifrado de comunicación de cliente y servidor pueden ser diferentes.
2. Después de verificar las identidades de ambas partes, el cliente también puede pasar la clave pública asimétrica generada por él mismo al servidor y comunicarse entre las dos partes a través de cifrado asimétrico.

Premisa de comunicación: el cliente ha obtenido el certificado digital del servidor. El certificado contiene la clave pública RSA del servidor. Para conocer el principio de los certificados digitales y otra información, lea este blog certificado digital .
Generalmente, cuando desarrollamos aplicaciones, ponemos un certificado digital en el programa por primera vez, cuando está a punto de caducar podemos descargar un nuevo certificado a través del servidor para guardarlo y ponerlo en uso.

duda:

1. ¿Por qué utilizar RSA para cifrar y descifrar el contenido de la comunicación?
Respuesta: Para la seguridad de los datos, la comunicación directa entre el cliente y el servidor puede ser atacada por piratas informáticos en múltiples niveles. El robo de datos y la manipulación de datos pueden llevarse a cabo disfrazándose como servidor o cliente.

2. ¿Por qué no obtener el certificado del servidor durante la primera llamada o descargarlo en un sitio web?
Respuesta: El sitio web que visita al principio puede no ser un sitio web real y el certificado descargado o transmitido también puede ser un certificado falso.

3. ¿Por qué utilizar tanto el cifrado como la firma para el contenido de las comunicaciones?
Respuesta: Aunque los "piratas informáticos" no pueden conocer el contenido cifrado, pueden modificarlo, como agregar una sección de contenido a la primera posición, reemplazar parte de la información y causar interferencia en la información. Vale la pena firmar la información mediante cifrado y hash de contenido, y se puede juzgar si el contenido de la comunicación se ha modificado y dañado, y si está completo.

4. ¿Por qué el cliente verifica la firma del servidor mediante el hash de una cadena aleatoria en lugar de hacerlo directamente mediante el cifrado y el descifrado?
Respuesta: Porque los "piratas informáticos" pueden encontrar la ley de cifrado enviando cadenas simples y regulares, como "0,1,2,3,4", etc., y descifrar el método de cifrado, lo que no es seguro. Al cifrar el valor hash de la cadena, después de que el cliente recibe el contenido, descifra el valor hash de la cadena y lo compara con el hash calculado a partir de la cadena pasada para verificar la firma del servidor.

5. ¿Cómo resolver el problema de los "piratas informáticos" que interceptan contenido cifrado y envían información repetidamente?
Respuesta: Agregue un número de serie y un número aleatorio al contenido de la comunicación. Si el cliente o servidor recibe la misma información, significa que la comunicación ha sido interferida y la comunicación debe detenerse para otro procesamiento. .

Resumen:
1. Se puede considerar que el cifrado de la información en la comunicación evita la fuga de datos y su descifrado y robo
. 2. La firma de datos es para determinar si los datos recibidos están completos para
garantizar que el cliente y el servidor puedan recibir datos cifrados completos que no puedan ser descifrados por partes irrelevantes. Es el punto central de la seguridad de los datos de comunicación de la red.

Adjuntar una clase de herramienta RSA

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
/**
 * 时间:2020/4/20 0020    星期一
 * 邮件:[email protected]
 * 说明:RSA非对称加密
 */
class RSAUtils {
    
    
    private final String CHARSET = "UTF-8";
    private final String RSA_ALGORITHM = "RSA";

    private Map<String, String> createKeys(int keySize) {
    
    
        //为RSA算法创建一个KeyPairGenerator对象
        KeyPairGenerator kpg;
        try {
    
    
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
    
    
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        //初始化KeyPairGenerator对象,密钥长度
        kpg.initialize(keySize);
        //生成密匙对
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());

        //得到私钥
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        Map<String, String> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);
        return keyPairMap;
    }

    /**
     * 得到公钥
     *
     * @param publicKey 密钥字符串(经过base64编码)
     */
    private RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
    
    
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
        return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
    }

    /**
     * 得到私钥
     * @param privateKey 密钥字符串(经过base64编码)
     */
    private RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
    
    
        //通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
        return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
    }

    /**
     * 公钥加密
     */
    private String publicEncrypt(String data, RSAPublicKey publicKey) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength());
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
    
    
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥解密
     *
     * @param data    待解密数据
     * @param privateKey    私钥
     */
    private String privateDecrypt(String data, RSAPrivateKey privateKey) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] bytes = Base64.getDecoder().decode(data);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, bytes, privateKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
    
    
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥加密
     *
     */
    public String privateEncrypt(String data, RSAPrivateKey privateKey) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] bytes = rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength());
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
    
    
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     */
    public String publicDecrypt(String data, RSAPublicKey publicKey) {
    
    
        try {
    
    
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] bytes = Base64.getDecoder().decode(data);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, bytes, publicKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
    
    
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    private byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
    
    
        int maxBlock;
        if (opmode == Cipher.DECRYPT_MODE) {
    
    
            maxBlock = keySize / 8;
        } else {
    
    
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
    
    
            while (datas.length > offSet) {
    
    
                if (datas.length - offSet > maxBlock) {
    
    
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                } else {
    
    
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        } catch (Exception e) {
    
    
            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        try {
    
    
            out.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return resultDatas;
    }

    public static void main(String[] args) throws Exception {
    
    
        RSAUtils rsaUtils = new RSAUtils();
        Map<String, String> keyMap = rsaUtils.createKeys(1024);
        String publicKey = keyMap.get("publicKey");
        String privateKey = keyMap.get("privateKey");
        System.out.println("公钥: \n\r" + publicKey);
        System.out.println("私钥: \n\r" + privateKey);

        System.out.println("公钥加密——私钥解密");
        String str = "孙子,我是你爸爸";
        System.out.println("\r明文:\r\n" + str);
        System.out.println("\r明文大小:\r\n" + str.getBytes().length);
        String encodedData = rsaUtils.publicEncrypt(str, rsaUtils.getPublicKey(publicKey));
        System.out.println("密文:\r\n" + encodedData);
        String decodedData = rsaUtils.privateDecrypt(encodedData, rsaUtils.getPrivateKey(privateKey));
        System.out.println("解密后文字: \r\n" + decodedData);
    }
}

该篇博客纯属个人观点和见解,如有错误恳请留言指正,万分感激!

Enlaces relacionados:

  1. Principio del algoritmo RSA
  2. Certificado digital para comunicación Https

Supongo que te gusta

Origin blog.csdn.net/luo_boke/article/details/106013674
Recomendado
Clasificación