您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關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 = 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: 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(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----- 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>
啟動服務后訪問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解密功能”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。