【Flask】前端RSA加密后端Python解密示例
来源:互联网 发布:开的淘宝店怎么找不到 编辑:程序博客网 时间:2024/05/29 08:49
前言
在使用 Flask 开发用户登录API的时候,我之前都是明文传输 username 和 password。这种传输方式有一定的安全隐患,password 可能会在传输过程中被窃听而造成用户密码的泄漏。
那么我认为解决该问题的方法是这样的:在前端页面对数据进行加密,然后再发送到后端进行处理。
这一篇文章是前端用 RSA 的 publicKey 进行加密,然后后端用 Python 进行解密的示例。
工具列表
- 后端:Python3
- Flask
- PyCrypto(PyCrytodome)
- 前端
- jsencrypt.js
后端使用Cryptodome
库进行密钥的生成和解密,前端则使用jsencrypt.js
库进行加密。
阅读提醒
本文主要是提供前端RSA加密后端Python解密代码示例,不会做太详细的说明,也不会有代码打包下载链接,原理与步骤请细读示例代码或查阅相关资料。
后端
下面首先说明Python后端所用到的工具。
PyCrypto和PyCrytodome
PyCrypto 可能是 Python 中密码学方面最有名的第三方软件包。可惜的是,它的开发工作于2012年就已停止。幸运的是,有一个该项目的分支取代了 PyCrypto ,那就是 PyCrytodome。
Linux下安装命令:
pip install pycryptodome
Windows下安装命令:
pip install pycryptodomex
PyCrytodome使用示例
安装好 pycryptodome 后,下面放上示例代码RSA_demo.py
。
#!/usr/bin/env python3# coding=utf-8# Author: yannanxiu"""create_rsa_key() - 创建RSA密钥my_encrypt_and_decrypt() - 加密解密测试"""from Cryptodome.PublicKey import RSAfrom Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5def create_rsa_key(password="123456"): """ 创建RSA密钥 步骤说明: 1、从 Crypto.PublicKey 包中导入 RSA,创建一个密码 2、生成 1024/2048 位的 RSA 密钥 3、调用 RSA 密钥实例的 exportKey 方法,传入密码、使用的 PKCS 标准以及加密方案这三个参数。 4、将私钥写入磁盘的文件。 5、使用方法链调用 publickey 和 exportKey 方法生成公钥,写入磁盘上的文件。 """ key = RSA.generate(1024) encrypted_key = key.exportKey(passphrase=password, pkcs=8, protection="scryptAndAES128-CBC") 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())def encrypt_and_decrypt_test(password="123456"): # 加载公钥 recipient_key = RSA.import_key( open("my_rsa_public.pem").read() ) cipher_rsa = PKCS1_v1_5.new(recipient_key) en_data = cipher_rsa.encrypt(b"123456") print(len(en_data), en_data) # 读取密钥 private_key = RSA.import_key( open("my_private_rsa_key.bin").read(), passphrase=password ) cipher_rsa = PKCS1_v1_5.new(private_key) data = cipher_rsa.decrypt(en_data, None) print(data)if __name__ == '__main__': # create_rsa_key() encrypt_and_decrypt_test()
其中create_rsa_key()
为创建密钥对,encrypt_and_decrypt_test()
为加密解密的测试,用起来很简单对吧?
既然知道如何在Python端解密数据了,那么下面就是前端的代码:
前端
前端所用到的主要工具是jsencrypt.js
。
jsencrypt.js简介
jsencrypt.js
是一个提供RSA加密、解密和密钥生成的JS库。其使用方式也非常简单。在其官网就有给出示例代码。
Flask工程示例
Python后端
新建一个Python脚本,取名为rsa_flask_demo.py
,把下面代码复制过去。
#!/usr/bin/env python3# coding=utf-8# Author: yannanxiuimport osfrom flask import Flask, render_template, request, current_appfrom Cryptodome.PublicKey import RSAfrom Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5import base64from urllib import parse# 获取当前路径curr_dir = os.path.dirname(os.path.realpath(__file__))private_key_file = os.path.join(curr_dir, "my_private_rsa_key.bin")public_key_file = os.path.join(curr_dir, "my_rsa_public.pem")app = Flask(__name__)def decrypt_data(inputdata, code="123456"): # URLDecode data = parse.unquote(inputdata) # base64decode data = base64.b64decode(data) private_key = RSA.import_key( open(curr_dir + "/my_private_rsa_key.bin").read(), passphrase=code ) # 使用 PKCS1_v1_5,不要用 PKCS1_OAEP # 使用 PKCS1_OAEP 的话,前端 jsencrypt.js 加密的数据解密不了 cipher_rsa = PKCS1_v1_5.new(private_key) # 当解密失败,会返回 sentinel sentinel = None ret = cipher_rsa.decrypt(data, sentinel) return ret@app.route('/', methods=["GET", "POST"])def rsa(): public_key = None if "GET" == request.method: with open(public_key_file) as file: public_key = file.read() elif "POST" == request.method: username = request.values.get("username") password = request.values.get("passwd") current_app.logger.debug("username:" + username + "\n" + "password:" + password) # decrypt username_ret = decrypt_data(username) password_ret = decrypt_data(password) if username_ret and password_ret: current_app.logger.debug(username_ret.decode() + " " + password_ret.decode()) return render_template("rsa_view.html", public_key=public_key)@app.route('/js_rsa_test', methods=["GET", "POST"])def js_rsa_test(): return render_template("js_rsa_test.html")if __name__ == '__main__': app.run(debug=True)
把rsa_flask_demo.py
与前面的RSA_demo.py
脚本放在一起,再用RSA_demo.py
生成一组密钥对。或者把前面生成密钥对文件放在同一个目录下也可以。
前端代码
在同一目录下新建一个templates
文件夹,用来存放Flask的前端模板。
在templates
文件夹新建rsa_view.html
,并拷贝下面代码过去,该HTML文件与Flask中的rsa()
相对应。
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script> <script src="http://passport.cnblogs.com/scripts/jsencrypt.min.js"></script> <script type="text/javascript"> // 使用jsencrypt类库加密js方法, function encryptRequest(reqUrl, data, publicKey) { var encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); // ajax请求发送的数据对象 var sendData = new Object(); // 将data数组赋给ajax对象 for (var key in data) { sendData[key] = encrypt.encrypt(data[key]); } console.info(sendData); $.ajax({ url: reqUrl, type: 'post', data: sendData, dataType: 'json', //contentType: 'application/json; charset=utf-8', success: function (data) { console.info(data); }, error: function (xhr) { //console.error('出错了'); } }); } // Call this code when the page is done loading. $(function () { $('#testme').click(function () { var data = []; data['username'] = $('#username').val(); data['passwd'] = $('#passwd').val(); var pkey = $('#pubkey').val(); encryptRequest('/', data, pkey); }); }); </script></head><body><form id="form1" runat="server"> <div> <label for="pubkey">Public Key</label><br/> <textarea id="pubkey" rows="15" cols="65"> {{ public_key }} </textarea><br/> <label for="input">Text to encrypt:</label><br/> name:<input id="username" name="username" type="text" value="user"></input><br/> password:<input id="passwd" name="passwd" type="password" value="123"></input><br/> <input id="testme" type="button" value="submit"/><br/> </div></form></body></html>
运行rsa_flask_demo.py
,访问http://127.0.0.1:5000/
,即可看到下面页面。直接点击submit按钮即可。
当后台页面打印:
--------------------------------------------------------------------------------DEBUG in rsa_flask_demo [F:/Flask/RSA_Flask/rsa_flask_demo.py:57]:user 123--------------------------------------------------------------------------------
即说明解密成功!
其他
rsa_flask_demo.py
中的js_rsa_test()
为JS脚本测试页面,其对应的HTML代码如下:
<!doctype html><html> <head> <title>JavaScript RSA Encryption</title> <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script> <script src="http://passport.cnblogs.com/scripts/jsencrypt.min.js"></script> <script type="text/javascript"> // Call this code when the page is done loading. $(function() { // Run a quick encryption/decryption when they click. $('#testme').click(function() { // Encrypt with the public key... var encrypt = new JSEncrypt(); encrypt.setPublicKey($('#pubkey').val()); var encrypted = encrypt.encrypt($('#input').val()); // Decrypt with the private key... var decrypt = new JSEncrypt(); decrypt.setPrivateKey($('#privkey').val()); var uncrypted = decrypt.decrypt(encrypted); // Now a simple check to see if the round-trip worked. if (uncrypted == $('#input').val()) { alert('It works!!!'); } else { alert('Something went wrong....'); } }); }); </script> </head> <body> <label for="privkey">Private Key</label><br/> <textarea id="privkey" rows="15" cols="65">-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQABAoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fvxTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeHm7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAFz/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIMV7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATeaTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5AzilpsLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Ozuku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876-----END RSA PRIVATE KEY-----</textarea><br/> <label for="pubkey">Public Key</label><br/> <textarea id="pubkey" rows="15" cols="65">-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB-----END PUBLIC KEY-----</textarea><br/> <label for="input">Text to encrypt:</label><br/> <textarea id="input" name="input" type="text" rows=4 cols=70>This is a test!</textarea><br/> <input id="testme" type="button" value="Test Me!!!" /><br/> </body></html>
启动服务后访问http://127.0.0.1:5000/js_rsa_test
即可。代码内容主要是先用jsencrypt.js
加密数据,再进行解密,如果成功则弹出It works!!!
对话框。不传输数据到后台,仅仅作为前端测试。
目录结构
│ my_private_rsa_key.bin│ my_rsa_public.pem│ RSA_demo.py│ rsa_flask_demo.py│└─templates js_rsa_test.html rsa_view.html
- 【Flask】前端RSA加密后端Python解密示例
- RSA前端加密后端解密
- RSA前端加密后端解密
- RSA非对称性前端加密后端解密
- RSA前端JS加密,后端JAVA解密实现
- RSA前端JS加密,后端JAVA解密实现
- RSA前端JS加密,后端JAVA解密实现
- RSA在前端加密后端解密的应用
- RSA实现JS前端加密,PHP后端解密
- RSA实现JS前端加密,PHP后端解密
- RSA实现JS前端加密,PHP后端解密
- AES前端加密后端解密
- base64之前端加密后端解密
- 前端登陆加密和后端解密
- 关于base64前端加密,后端解密
- RSA前端加密,java后台解密
- RSA加密 解密 示例及源码
- 前端加密后端解密之Base64通用加密处理
- Python中操作mysql的pymysql模块详解
- CentOS6 安装教程
- Java集合体系
- Java遍历List,删除自身元素
- JavaScript 学习
- 【Flask】前端RSA加密后端Python解密示例
- 查找算法(2)--二分查找算法
- 五分钟读懂UML类图
- springboot和Druid整合(三)
- python绘图函数
- 介绍一下 OpenLDAP 2.4.45 相关的头文件和库文件
- Bigdecimal运算及注意事项
- TextView 中插入网络图片
- android lint检查无用资源文件删除