Skip to content

对称加密和非对称加密的应用

概要内容

  • 什么是对称加密
  • 对称加密demo
  • 什么是非对称加密
  • 非对称加密demo
  • 对称加密与非对称加密组合使用
  • 介绍一套可行的混合加密方案,怎么应用到接口数据加密中
  • Demo源码工程

什么是对称加密

  • 定义:

    对称密钥算法(英语:Symmetric-key algorithm)又称为对称加密、私钥加密、共享密钥加密,是密码学中的一类加密算法。这类算法在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥

  • 优点:

    算法公开、计算量小、加密速度快、加密效率高,适合对大量数据进行加密的场景。 比如 HLS(HTTP Live Streaming)普通加密场景中,一般会使用 AES-128 对称加密算法对 TS 切片进行加密,以保证多媒体资源安全

  • 缺点:

    安全性不高,只要拿到秘钥就可以把数据解开

  • 对称加密的过程:

    发送方使用密钥将明文数据加密成密文,然后发送出去,接收方收到密文后,使用同一个密钥将密文解密成明文读取

  • 个人理解:

    对称加密就好比一把锁的钥匙,一个密码箱存了东西,如果你有钥匙就可以把密码箱里面的宝贝取走


对称加密demo

this.key = CryptoJS.enc.Utf8.parse("0123456789abcdef");
this.iv = CryptoJS.enc.Utf8.parse("abcdef0123456789");
/**
* AES 加密
* @param iv
* @param key
* @param content 加密数据
* @returns {string}
* @private
*/
__aesEncrypt(iv, key, content) {
    let text = CryptoJS.enc.Utf8.parse(JSON.stringify(content));
    let encrypted = CryptoJS.AES.encrypt(text, key,
        {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });
    return encrypted.toString();
},

/**
* AES 解密
* @param iv
* @param key
* @param content  解密数据
* @returns {string}
* @private
*/
__aesDecrypt(iv, key, content) {
    let decrypt = CryptoJS.AES.decrypt(content, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
    });
    let decryptText = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptText.replace(/\"/g, "");
},


什么是非对称加密

  • 定义:

    非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。 因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法

  • 优点:

    安全性更高,公钥是公开的,私钥是自己保存的,不需要将私钥提供给别人

  • 缺点

    加解密速度慢,只适合应对小数据加解密

  • 对称加密的过程:

  • 个人理解

    非对称加密:公钥就好比未锁的密码箱,只能存东西进去然后锁住。秘钥就好比密码箱的钥匙,可以打开秘密箱然后把里面的宝贝取走

  • 非对称加密demo

this.rsaEncryptor = new JSEncrypt();
this.rsaEncryptor.setPublicKey(this.rsa_pub_key);
this.rsaDecryptor = new JSEncrypt();
this.rsaDecryptor.setPrivateKey(this.rsa_pri_key);

/**
* RSA 加密
* @param content
* @returns {CipherParams|PromiseLike<ArrayBuffer>}
* @private
*/
__rsaEncrypt(content) {
    return this.rsaEncryptor.encrypt(content);
},
/**
* RSA 解密
* @param content
* @returns {WordArray|PromiseLike<ArrayBuffer>}
* @private
*/
__rsaDecrypt(content) {
    return this.rsaDecryptor.decrypt(content);
},

对称加密与非对称加密组合使用

现在对称加密和非对称加密的缺点我们都知道了,那就结合对称加密和非对称加密的优点来个demo,思路:针对小数据对称加密的iv和key,采用非对称加密;针对大数据data采用对称加密。

/**
* 混合加密
* @param iv
* @param key
* @param content
* @returns {{data: string, iv: (CipherParams|PromiseLike<ArrayBuffer>), key: (CipherParams|PromiseLike<ArrayBuffer>)}}
* @private
*/
__hybirdEncrypt(iv, key, content) {
    const aesEncryptData = this.__aesEncrypt(iv, key, content);
    const rsaEncryptIv = this.__rsaEncrypt(iv);
    const rsaEncryptKey = this.__rsaEncrypt(key);
    return {
        iv: rsaEncryptIv,
        key: rsaEncryptKey,
        data: aesEncryptData,
    };
},

/**
* 混合解密
* @param encryptInfo
* @returns {string}
* @private
*/
__hybirdDecrypt(encryptInfo) {
    const iv = this.rsaDecryptor.decrypt(encryptInfo.iv);
    const key = this.rsaDecryptor.decrypt(encryptInfo.key);
    const data = encryptInfo.data;
    return this.__aesDecrypt(iv, key, data);
}

介绍一套可行混合加密方案,怎么应用到接口数据加密中。流程图如下:

  • 思路如下:
    • 第1步:创建一套RSA 公私钥,公钥前端拿着,私钥服务端拿着
    • 第2步:前端为每一个网络请求生成RequestID
    • 第3步:客户端生成AES Key,然后将RequestID 作为Key,AES Key 作为Value 存内存
    • 第4步:客户端用生成的AES Key 加密请求数据Request Data,用RSA公钥对AES Key进行加密,同时把requestID、加密数据、加密AES Key 发送给服务端
    • 第5步:服务端用RSA私钥解密被加密的AES Key,然后再用解开的AES Key 对RequestData数据进行解密
    • 第6步:服务端用AES Key对响应数据ResposneData加密+RequestID、返回给前端
    • 第7步:前端根据服务端返回的RequestID 取出内存的AES key, 用AES key 解密Resposne Data数据,用完后删除内存RequestID 的AES key 数据。
    • 最后:前端每次发送请求都创建AES Key 去加密数据,收到服务端响应数据解密用完后,就删除掉内存中的AES Key数据,如此循环就用一套RSA公私钥解决混合加密问题
  • 流程图:

Demo源码工程:

最后:

由于对称加密DES安全性已不太强,所以就选择了替代品AES。非常感谢阿宝哥提供的玩转混合加密文章,讲得通俗易懂,让我受益匪浅。最后阿宝哥提到把AES key 存放内存容易让他人搞到AES Key。所以我就去了解Web如何防调试、代 码怎么混淆等,下一篇:Web如何防调试


参考文献:


更多相关资料:


以上: 如发现有问题,欢迎留言指出,我及时更正

Released under the MIT License.