Flask框架实现的前端RSA加密与后端Python解密功能详
本⽂实例讲述了Flask框架实现的前端RSA加密与后端Python解密功能。分享给⼤家供⼤家参考,具体如下:
前⾔
在使⽤ 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 RSA
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5
def create_rsa_key(password="123456"):
"""
创建RSA密钥
步骤说明:
1、从 Crypto.PublicKey 包中导⼊ RSA,创建⼀个密码
2、⽣成 1024/2048 位的 RSA 密钥
3、调⽤ RSA 密钥实例的 exportKey ⽅法,传⼊密码、使⽤的 PKCS 标准以及加密⽅案这三个参数。
4、将私钥写⼊磁盘的⽂件。
5、使⽤⽅法链调⽤ publickey 和 exportKey ⽅法⽣成公钥,写⼊磁盘上的⽂件。
"""
key = ate(1024)
encrypted_key = portKey(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_w(recipient_key)
en_data = pt(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_w(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: yannanxiu
import os
from flask import Flask, render_template, request, current_app
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5
import base64
from urllib import parse
# 获取当前路径
curr_dir = os.path.dirname(alpath(__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_w(private_key)
# 当解密失败,会返回 sentinel
sentinel = None
ret = cipher_rsa.decrypt(data, sentinel)
return ret
@ute('/', methods=["GET", "POST"])
def rsa():
public_key = None
if "GET" == hod:
with open(public_key_file) as file:
public_key = ad()
elif "POST" == hod:
username = ("username")
password = ("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)
@ute('/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="/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script src="code.jquery/jquery-1.8.3.min.js"></script>
<script src="passportblogs/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] = pt(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) {
//('出错了');
}
});
}
// 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>
当后台页⾯打印:
-
-------------------------------------------------------------------------------
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="code.jquery/jquery-1.8.3.min.js"></script>
<script src="passportblogs/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
var encrypt = new JSEncrypt();
encrypt.setPublicKey($('#pubkey').val());
var encrypted = pt($('#input').val());
// Decrypt with the
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');
}jquery框架原理
else {
alert('Something ');
}
});
});
</script>
</head>
<body>
<label for="privkey">Private Key</label><br/>
<textarea id="privkey" rows="15" cols="65">-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ
WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR
aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv
xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH
m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd
8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF
z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5
rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM
V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz
uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876
-----END RSA PRIVATE KEY-----</textarea><br/>
<label for="pubkey">Public Key</label><br/>
<textarea id="pubkey" rows="15" cols="65">-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN
FOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76
xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4
gwQco1KRMDSmXSMkDwIDAQAB
-----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>
⽬录结构
│  my_private_rsa_key.bin
│  my_rsa_public.pem
│  RSA_demo.py
│  rsa_flask_demo.py
└─templates
js_rsa_test.html
rsa_view.html
PS:关于加密解密感兴趣的朋友还可以参考本站在线⼯具:
希望本⽂所述对⼤家基于flask框架的Python程序设计有所帮助。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。