Flask框架實(shí)現(xiàn)的前端RSA加密與后端Python解密功能詳解
本文實(shí)例講述了Flask框架實(shí)現(xiàn)的前端RSA加密與后端Python解密功能。分享給大家供大家參考,具體如下:
前言
在使用 Flask 開發(fā)用戶登錄API的時候,我之前都是明文傳輸 username 和 password。這種傳輸方式有一定的安全隱患,password 可能會在傳輸過程中被竊聽而造成用戶密碼的泄漏。
那么我認(rèn)為解決該問題的方法是這樣的:在前端頁面對數(shù)據(jù)進(jìn)行加密,然后再發(fā)送到后端進(jìn)行處理。
這一篇文章是前端用 RSA 的 publicKey 進(jìn)行加密,然后后端用 Python 進(jìn)行解密的示例。
工具列表
- 后端:Python3
- Flask
- PyCrypto(PyCrytodome)
- 前端
后端使用Cryptodome庫進(jìn)行密鑰的生成和解密,前端則使用jsencrypt.js庫進(jìn)行加密。
閱讀提醒
本文主要是提供前端RSA加密后端Python解密代碼示例,不會做太詳細(xì)的說明,也不會有代碼打包下載鏈接,原理與步驟請細(xì)讀示例代碼或查閱相關(guān)資料。
后端
下面首先說明Python后端所用到的工具。
PyCrypto和PyCrytodome
PyCrypto 可能是 Python 中密碼學(xué)方面最有名的第三方軟件包??上У氖牵拈_發(fā)工作于2012年就已停止。幸運(yùn)的是,有一個該項(xiàng)目的分支取代了 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() - 創(chuàng)建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"):
"""
創(chuàng)建RSA密鑰
步驟說明:
1、從 Crypto.PublicKey 包中導(dǎo)入 RSA,創(chuàng)建一個密碼
2、生成 1024/2048 位的 RSA 密鑰
3、調(diào)用 RSA 密鑰實(shí)例的 exportKey 方法,傳入密碼、使用的 PKCS 標(biāo)準(zhǔn)以及加密方案這三個參數(shù)。
4、將私鑰寫入磁盤的文件。
5、使用方法鏈調(diào)用 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()為創(chuàng)建密鑰對,encrypt_and_decrypt_test()為加密解密的測試,用起來很簡單對吧?
既然知道如何在Python端解密數(shù)據(jù)了,那么下面就是前端的代碼:
前端
前端所用到的主要工具是jsencrypt.js。
jsencrypt.js簡介
jsencrypt.js是一個提供RSA加密、解密和密鑰生成的JS庫。其使用方式也非常簡單。在其官網(wǎng)就有給出示例代碼。
Flask工程示例
Python后端
新建一個Python腳本,取名為rsa_flask_demo.py,把下面代碼復(fù)制過去。
#!/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
# 獲取當(dāng)前路徑
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 加密的數(shù)據(jù)解密不了
cipher_rsa = PKCS1_v1_5.new(private_key)
# 當(dāng)解密失敗,會返回 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()相對應(yīng)。
<!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請求發(fā)送的數(shù)據(jù)對象
var sendData = new Object();
// 將data數(shù)組賦給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>
運(yùn)行rsa_flask_demo.py,訪問http://127.0.0.1:5000/,即可看到下面頁面。直接點(diǎn)擊submit按鈕即可。

當(dāng)后臺頁面打?。?/p>
--------------------------------------------------------------------------------
DEBUG in rsa_flask_demo [F:/Flask/RSA_Flask/rsa_flask_demo.py:57]:
user 123
--------------------------------------------------------------------------------
即說明解密成功!
其他
rsa_flask_demo.py中的js_rsa_test()為JS腳本測試頁面,其對應(yīng)的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-----
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>
啟動服務(wù)后訪問http://127.0.0.1:5000/js_rsa_test即可。代碼內(nèi)容主要是先用jsencrypt.js加密數(shù)據(jù),再進(jìn)行解密,如果成功則彈出It works!!!對話框。不傳輸數(shù)據(jù)到后臺,僅僅作為前端測試。
目錄結(jié)構(gòu)
│ 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:關(guān)于加密解密感興趣的朋友還可以參考本站在線工具:
在線RSA加密/解密工具:
http://tools.jb51.net/password/rsa_encode
文字在線加密解密工具(包含AES、DES、RC4等):
http://tools.jb51.net/password/txt_encode
MD5在線加密工具:
http://tools.jb51.net/password/CreateMD5Password
在線散列/哈希算法加密工具:
http://tools.jb51.net/password/hash_encrypt
在線MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha
在線sha1/sha224/sha256/sha384/sha512加密工具:
http://tools.jb51.net/password/sha_encode
希望本文所述對大家基于flask框架的Python程序設(shè)計(jì)有所幫助。
- 利用Python實(shí)現(xiàn)RSA加密解密方法實(shí)例
- Python3加密解密庫Crypto的RSA加解密和簽名/驗(yàn)簽實(shí)現(xiàn)方法實(shí)例
- Python如何基于rsa模塊實(shí)現(xiàn)非對稱加密與解密
- Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加簽驗(yàn)簽
- python中的RSA加密與解密實(shí)例解析
- python rsa實(shí)現(xiàn)數(shù)據(jù)加密和解密、簽名加密和驗(yàn)簽功能
- Python下實(shí)現(xiàn)的RSA加密/解密及簽名/驗(yàn)證功能示例
- python rsa 加密解密
- python實(shí)現(xiàn)RSA加密(解密)算法
- Python實(shí)現(xiàn)RSA加密解密
相關(guān)文章
python數(shù)據(jù)分析之用sklearn預(yù)測糖尿病
這篇文章主要介紹了python數(shù)據(jù)分析之用sklearn預(yù)測糖尿病,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)python數(shù)據(jù)分析的小伙伴們有很好地幫助,需要的朋友可以參考下2021-04-04
詳解Python中字符串前“b”,“r”,“u”,“f”的作用
這篇文章主要介紹了Python中字符串前“b”,“r”,“u”,“f”的作用,感興趣的朋友跟隨小編一起看看吧2019-12-12
Python 通過爬蟲實(shí)現(xiàn)GitHub網(wǎng)頁的模擬登錄的示例代碼
這篇文章主要介紹了Python 通過爬蟲實(shí)現(xiàn)GitHub網(wǎng)頁的模擬登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
快速解決Django關(guān)閉Debug模式無法加載media圖片與static靜態(tài)文件
這篇文章主要介紹了快速解決Django關(guān)閉Debug模式無法加載media圖片與static靜態(tài)文件的操作方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04

