侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Flask框架实现的前端RSA加密与后端Python解密功能详解

Python  /  管理员 发布于 7年前   244

本文实例讲述了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 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 [email protected]('/', 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

PS:关于加密解密感兴趣的朋友还可以参考本站在线工具:

在线RSA加密/解密工具:
http://tools..net.cn/password/rsa_encode

文字在线加密解密工具(包含AES、DES、RC4等):
http://tools..net.cn/password/txt_encode

MD5在线加密工具:
http://tools..net.cn/password/CreateMD5Password

在线散列/哈希算法加密工具:
http://tools..net.cn/password/hash_encrypt

在线MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools..net.cn/password/hash_md5_sha

在线sha1/sha224/sha256/sha384/sha512加密工具:
http://tools..net.cn/password/sha_encode

希望本文所述对大家基于flask框架的Python程序设计有所帮助。


  • 上一条:
    python批量读取文件名并写入txt文件中
    下一条:
    Python学习笔记之列表推导式实例分析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客