dajngo 前后端传输数据进行加密 RSA加密
发布日期:2022-02-17 04:52:26 浏览次数:11 分类:技术文章

本文共 3350 字,大约阅读时间需要 11 分钟。

利用django中pycryptodome模块进行数据加密(不对称加密,即生成公钥和私钥,前台用公钥加密,后台接收到机密数据后利用私钥解密)

注意:pycrypto,pycrytodome和crypto是一个东西,crypto在python上面的名字是pycrypto它是一个第三方库,但是已经停止更新三年了,所以不建议安装这个库;

安装好pycrytodome,可卸载另外两个模块,否则会在代码中导入时发生冲突。

可直接通过pip(pip3) install pycrytodome在线安装,也可去下载pycrytodome安装包进行安装(选择和python对应的版本)

代码示例:

注意:安装的是pycrytodome,在项目中导入的是Crypto

1、后端代码

from Crypto.PublicKey import RSA

from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
import base64
from urllib import parse
from django.shortcuts import render

def create_rsa_key():
    """
    创建RSA密钥
    步骤说明:
    1、从 Crypto.PublicKey 包中导入 RSA,创建一个密码
    2、生成 1024/2048 位的 RSA 密钥
    3、调用 RSA 密钥实例的 exportKey 方法,传入口令、使用的 PKCS 标准以及加密方案这三个参数。
    4、将私钥写入磁盘的文件。
    5、使用方法链调用 publickey 和 exportKey 方法生成公钥,写入磁盘上的文件。
    """
    # 利用伪随机数来生成私钥和公钥
    random_generator = Random.new().read
    key = RSA.generate(2048,random_generator) #生成 1024/2048 位的 RSA 密钥
    encrypted_key = key.exportKey() #私钥
    # public_key = key.publickey().exportKey() #公钥
    with open("my_private_rsa_key.bin", "wb") as f:#私钥写入磁盘
        f.write(encrypted_key)
    with open("my_rsa_public.pem", "wb") as f: #公钥写入磁盘
        f.write(key.publickey().exportKey())    #一般生成的密钥文件会直接生成到项目的根目录下

 

# 向前台发送公钥

class Public_Key(LoginRequiredMixin, View):
    def post(self, request):

        public_key = open("/xx/xx/xxxxxxx/my_rsa_public.pem").read()

        return HttpResponse(public_key)
 

2、前端js代码

// 前端js获取公钥,用公钥对传输数据进行加密(需要注意的是要用到一个对应的加密js文件,jsencrypt.min.js,可以在base.html文件导入,jsencrypt.min.js可从网上下载,放到js文件夹下)

    var public_key
    var encrypt = new JSEncrypt();
     // 获取公钥
    $.ajax({
        url:"/xxx/xxxxxx/",
        type:"post",
        data:{
            'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
        },
        success:function(data){
            public_key = data
            encrypt.setPublicKey(public_key);
        }
    })

 

// 对传输数据进行加密(data: {"activetype": encrypt.encrypt("repasd"), "repasd": encrypt.encrypt(repasd), "uid":encrypt.encrypt(puserid.toString()), "msg_code": encrypt.encrypt(msg_code)},)

$.ajax({

                        type: 'post',
                        url: "/xxx/xxxxx/",
                        dataType: "json",
                        headers: {"X-CSRFtoken": $("[name='csrfmiddlewaretoken']").val()},
                        data: {

                                  "activetype": encrypt.encrypt("repasd"),

                                  "repasd": encrypt.encrypt(repasd),                                                                                                                                                        "uid":encrypt.encrypt(puserid.toString()),

                                   "msg_code": encrypt.encrypt(msg_code)

                        },

                        success: function (data) {
                            // console.log(data)
                            if (data.code == 0) {
                                layer.close(index);
                                layer.open({
                                        content: '<span>' + data.msg + '</span>'
                                        , yes: function (index, layero) {
                                            //do something
                                            layer.close(index); //如果设定了yes回调,需进行手工关闭
                                            // alert({name: ""})
                                        }
                                    }
                                )

                            } 

                        },
                        error: function (xhr, type) {
                            // layer.close();
                            layer.open({
                                    content: '<span>' + '系统错误,重置失败' + '</span>'
                                }
                            )
                        }
                    });

 

3、后端解密代码

#解密过程,inputdata为前台公钥加密的数据

def decrypt_data(inputdata):

    data = parse.unquote(inputdata)

    # base64decode
    data = base64.b64decode(data)
    # 读取密钥
    private_key = RSA.import_key(
        open("/xx/xxxxxxx/my_private_rsa_key.bin").read())     # 路径需要准确
    # 使用 PKCS1_v1_5解密
    cipher_rsa = PKCS1_v1_5.new(private_key)
    # 当解密失败,会返回 sentinel
    sentinel = None
    ret = cipher_rsa.decrypt(data, sentinel)
    return ret.decode()  # 解码

基本流程到此结束。

说几个注意点(本人碰到的坑):

注意:

             1、前端需要被公钥加密的数据type为字符串,int型需要转为str型。

             2、后台无法解密前端加密数据接

                          (1)首先检查前台是否获取到公钥,数据是否机密成功,可从console打印查看

                          (2)检查前台接收到的公钥与项目中保存的文件公钥是否一致(这个是常见的,由于后台代码创建密钥的代码位置原因,每次刷新页面创建一次密钥,都会覆盖之前的密钥,使得之前传输到前台的公钥报废,导致后台无法解密成功,个人建议,1、可以将创建密钥代码写到单独一个文件,启动项目时,被运行,这样只要不关闭项目,密钥就不会改变,2、可以将创建密钥代码写到单独一个文件,定时去执行,每隔一段时间刷新一次密钥,3、懒人用法,如果登录后跳转的index页面不需要进行数据加密,可以将创建密钥代码卸载这,每次登陆就去创建一次密钥。)

暂时写到这,后面想到什么再补充

 

jsencrypt.min.js可自行下载。 提取码:9kk2

 

转载地址:https://blog.csdn.net/qq_41429841/article/details/107834127 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:djnago Excel数据上传进度条
下一篇:Java异步调用实现并发上传下载SMB共享文件

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月03日 00时38分11秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章