主页 > imtoken钱包下载安卓版 > 前后端分离项目接口数据加密的秘钥交换逻辑(RSA、AES)

前后端分离项目接口数据加密的秘钥交换逻辑(RSA、AES)

imtoken钱包下载安卓版 2023-03-30 07:32:04

本文由另一篇文章补充,请查看《前后端分离项目接口数据加密的数据加密密钥交换逻辑(补充:MITM man-in-the-middle attack)》

前后端分离 在项目中,往往需要传递一些敏感信息,比如密码、金额等,签名验证算法只能保证数据不被篡改,而不能保存数据保密。如果用户输入的密码以明文形式传输,则将通过网络传输。虽然大部分网络运营商不会截取网络传输的内容,但不能排除用户连接的WiFi网络是否为钓鱼网络,因此在传输敏感信息时需要加密。本文讨论如何安全地客户端和服务器交换密钥。

加密算法的选择,RSA 或 AES

在涉及到加密和解密时,涉及到加密和解密算法的选择。比较常见的是非对称加密RSA和对称加密AES。有哪些功能和选项?我们一一解释

私钥好破解吗

RSA 非对称加密

RSA算法会生成两个密钥,一个公钥和一个私钥,用公钥加密的数据必须用私钥解密,这样做的好处是只有服务器有私钥,没有人否则可以解密。但是他有一个很致命的弱点,就是加密内容的长度不能大于秘钥的长度。以 RSA 1024 为例,PKCS#1 建议的填充占用 11 个字节。这样,128字节(1024bits)-减去11字节就是117字节,也就是说我们最多只能用RSA 1024加密117字节的内容,超过这个内容会报错,但往往我们要传输的内容很大,不能限制。增加密钥长度。而且在移动设备上的性能有限,不适合大量的加解密操作。所以我们仍然需要 AES。

AES 对称加密

私钥好破解吗

由于上面的 RSA 受到加密密钥长度的限制,所以我们还需要 AES 加密。 AES 的优点是无论明文有多大,它都可以加密和解密。但缺点是不区分私钥和公钥,只有一个密钥,知道密钥的任何人都可以加密和解密信息。

结合 RSA 和 AES 以相互补充

RSA和AES各有优缺点私钥好破解吗,如果我们一起使用,可以取长补短,可以使用RSA来保护AES的秘钥,保证只有两方知道AES的秘钥私钥好破解吗,而AES可以加密任意长度的信息,从而解决了各自的不足。

私钥好破解吗

密钥交换逻辑

一、客户端向服务器申请RSA公钥;服务器生成一个 RSA 密钥对并将公钥发送给客户端。我们将其命名为“服务器公钥”

二、客户端收到服务器给的“服务器公钥”,客户端生成自己的RSA密钥对,我们命名为“客户端公钥”,客户端使用“服务器公钥”加密自己的“客户端公钥”并将其发送到服务器

私钥好破解吗

三、服务器接收到客户端的请求,使用“服务器私钥”“解密”得到“客户端公钥”

四、服务端生成“AES密钥”,使用“客户端公钥”对“AES密钥”进行加密并发送给客户端

五、客户端使用“客户端私钥”解密得到“AES密钥”

私钥好破解吗

后续双方交互使用“AES密钥”进行加解密,完成密钥交换过程。

秘钥交换逻辑

示例代码:

@Test
public void reaTest() {
    //服务器端的
    Map serverKeyMap = RSAUtils.genKeyPair(2048);
    //客户端的
    Map clientKeyMap = RSAUtils.genKeyPair(1024);
    String clientPubKey = clientKeyMap.get(0);
    try {
        //客户端使用服务器公钥加密自己的公钥
        String encrypt = RSAUtils.encrypt(clientPubKey, serverKeyMap.get(0));
        //服务器端使用自己的私钥解密拿到客户端公钥
        Assert.assertEquals(clientPubKey, RSAUtils.decrypt(encrypt, serverKeyMap.get(1)));
        String AESkey = "aeskey123456";
        //使用客户端的公钥加密AES的秘钥
        String encryptAES = RSAUtils.encrypt(AESkey, clientPubKey);
        //客户端用自己的私钥解密拿到AES的秘钥
        Assert.assertEquals(AESkey, RSAUtils.decrypt(encryptAES, clientKeyMap.get(1)));
    } catch (Exception ex) {
        ex.printStackTrace();
        Assert.assertNull(ex);
    }
}