如何用Python 加密文件


Posted in Python onSeptember 10, 2020

生活中,有时候我们需要对一些重要的文件进行加密,Python 提供了诸如 hashlib,base64 等便于使用的加密库。

但对于日常学习而言,我们可以借助异或操作,实现一个简单的文件加密程序,从而强化自身的编程能力。

基础知识

在 Python 中异或操作符为:^,也可以记作 XOR。按位异或的意思是:相同值异或为 0,不同值异或为 1。具体来讲,有四种可能:0 ^ 0 = 0,0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。我们还可总结出规律(A 为 0 或 1):0 和 A 异或为 A本身;1 和 A 异或为 A 反。

让我们想看看一位二进制数满足的性质:

  • 一位二进制数与自身的异或值为 0

b ^ b = 0

  • 异或操作满足交换律

a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c

  • 0 与 a 的异或为 a

(a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a

易知,对任意长二进制数都满足上述性质。

原理

通过了解异或操作的性质,加密原理就非常清晰了。

加密操作:

首先将文件转换成二进制数,再生成与该二进制数等长的随机密钥,将二进制数与密钥进行异或操作,得到加密后的二进制数。

解密操作:

将加密后的二进制程序与密钥进行异或操作,就得到原二进制数,最后将原二进制数恢复成文本文件。

生成随机密钥:

secrets 库是 Python 3.6 引入的伪随机数模块,适合生成随机密钥。token_bytes 函数接受一个 int 参数,用于指定随机字节串的长度。int.from_bytes 把字节串转换为 int,也就是我们需要的二进制数。

from secrets import token_bytes

def random_key(length):
  key = token_bytes(nbytes=length)
  key_int = int.from_bytes(key, 'big')
  return key_int

加密单元:

encrypt 函数接受一个 str 对象,返回元组 (int, int)。通过 encode 方法,我们将字符串编码成字节串。int.from_bytes 函数将字节串转换为 int 对象。最后对二进制对象和随机密钥进行异或操作,就得到了加密文本。

def encrypt(raw):
  raw_bytes = raw.encode()
  raw_int = int.from_bytes(raw_bytes, 'big')
  key_int = random_key(len(raw_bytes))
  return raw_int ^ key_int, key_int

解密单元:

decrypt 接受两个 int 对象,分别为加密文本和随机密钥。首先对两者进行异或操作,计算解密出来的 int 对象所占比特数。decrypted.bit_length 函数得到的是二进制数的位数,除以 8 可以得到所占比特大小。为了防止,1 ~ 7 位的二进制数整除 8 得到 0,所以要加上 7,然后再进行整除 8 的操作。使用 int.to_bytes 函数将解密之后的 int 的对象转换成 bytes 对象。最后通过 decode 方法,将字节串转换成字符串。

def decrypt(encrypted, key_int):
  decrypted = encrypted ^ key_int
  length = (decrypted.bit_length() + 7) // 8
  decrypted_bytes = int.to_bytes(decrypted, length, 'big') 
  return decrypted_bytes.decode()

利用上述函数,我们可以很轻松对文本文件进行加密、解密操作。

>>> raw = '画图省识春风面,环?空归夜月魂'
>>> encrypted = encrypt(raw)
>>> encrypted
(217447100157746604585...,
 9697901906831571319...)
>>> decrypt(*encrypted)
'画图省识春风面,环?空归夜月魂'

加密文本文件

path 为待加密文件的地址,如果不指定密钥地址,则在该目录下新建目录和文件。

import json
from pathlib import Path

def encrypt_file(path, key_path=None, *, encoding='utf-8'):
  path = Path(path)
  cwd = path.cwd() / path.name.split('.')[0]
  path_encrypted = cwd / path.name 
  if key_path is None:
    key_path = cwd / 'key'
  if not cwd.exists():
    cwd.mkdir()
    path_encrypted.touch()
    key_path.touch()

  with path.open('rt', encoding=encoding) as f1, \
    path_encrypted.open('wt', encoding=encoding) as f2, \
      key_path.open('wt', encoding=encoding) as f3:
    encrypted, key = encrypt(f1.read())
    json.dump(encrypted, f2)
    json.dump(key, f3)

解密文件

def decrypt_file(path_encrypted, key_path=None, *, encoding='utf-8'):
  path_encrypted = Path(path_encrypted)
  cwd = path_encrypted.cwd()
  path_decrypted = cwd / 'decrypted' 
  if not path_decrypted.exists():
    path_decrypted.mkdir()
    path_decrypted /= path_encrypted.name
    path_decrypted.touch()
  if key_path is None:
    key_path = cwd / 'key'
  with path_encrypted.open('rt', encoding=encoding) as f1, \
    key_path.open('rt', encoding=encoding) as f2, \
    path_decrypted.open('wt', encoding=encoding) as f3:
    decrypted = decrypt(json.load(f1), json.load(f2))
    f3.write(decrypted)

执行完加密、解密文件操作,得到的解密文件与原文件相同,示意图如下:

如何用Python 加密文件

以上就是如何用Python 加密文件的详细内容,更多关于Python 加密文件的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python multiprocessing.Manager介绍和实例(进程间共享数据)
Nov 21 Python
Python中用PIL库批量给图片加上序号的教程
May 06 Python
Python黑魔法Descriptor描述符的实例解析
Jun 02 Python
python 性能优化方法小结
Mar 31 Python
Tensorflow之构建自己的图片数据集TFrecords的方法
Feb 07 Python
Python多叉树的构造及取出节点数据(treelib)的方法
Aug 09 Python
python字符串替换re.sub()方法解析
Sep 18 Python
使用浏览器访问python写的服务器程序
Oct 10 Python
pygame库实现移动底座弹球小游戏
Apr 14 Python
Python RabbitMQ实现简单的进程间通信示例
Jul 02 Python
关于python scrapy中添加cookie踩坑记录
Nov 17 Python
Python编写可视化界面的全过程(Python+PyCharm+PyQt)
May 17 Python
Python 高效编程技巧分享
Sep 10 #Python
python操作redis数据库的三种方法
Sep 10 #Python
Python计算矩阵的和积的实例详解
Sep 10 #Python
python如何运行js语句
Sep 09 #Python
python如何爬取动态网站
Sep 09 #Python
python如何停止递归
Sep 09 #Python
python能做哪些生活有趣的事情
Sep 09 #Python
You might like
深入extjs与php参数交互的详解
2013/06/25 PHP
ThinkPHP3.1新特性之多层MVC的支持
2014/06/19 PHP
CI框架给视图添加动态数据
2014/12/01 PHP
php判断一个数组是否为有序的方法
2015/03/27 PHP
PHP使用mysqldump命令导出数据库
2015/04/14 PHP
PHP获取网站中各文章的第一张图片的代码示例
2016/05/20 PHP
PHP高并发和大流量解决方案整理
2019/12/24 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
2019/12/30 PHP
根据IP的地址,区分不同的地区,查看不同的网站页面的js代码
2013/02/26 Javascript
Ext中下拉列表ComboBox组件store数据格式用法介绍
2013/07/15 Javascript
使用js检测浏览器是否支持html5中的video标签的方法
2014/03/12 Javascript
jQuery横向擦除焦点图特效代码分享
2015/09/06 Javascript
AngularJS 模型详细介绍及实例代码
2016/07/27 Javascript
js正则表达式注册页面表单验证
2016/10/11 Javascript
工作中常用的js、jquery自定义扩展函数代码片段汇总
2016/12/22 Javascript
vue.js选中动态绑定的radio的指定项
2017/06/02 Javascript
基于Jquery Ajax type的4种类型(详解)
2017/08/02 jQuery
Bootstrap栅格系统的使用详解
2017/10/30 Javascript
Vue组件之高德地图地址选择功能的实例代码
2019/06/21 Javascript
JS如何在数组指定位置插入元素
2020/03/10 Javascript
用Python从零实现贝叶斯分类器的机器学习的教程
2015/03/31 Python
Python爬取国外天气预报网站的方法
2015/07/10 Python
Python内置的HTTP协议服务器SimpleHTTPServer使用指南
2016/03/30 Python
Django Rest framework之认证的实现代码
2018/12/17 Python
三步解决python PermissionError: [WinError 5]拒绝访问的情况
2020/04/22 Python
HTML5之HTML元素扩展(下)—增强的Form表单元素值得关注
2013/01/31 HTML / CSS
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
2013/11/07 HTML / CSS
小天鹅官方商城:LittleSwan
2017/06/16 全球购物
澳大利亚在线划船、露营和钓鱼商店:BCF Australia
2020/03/22 全球购物
项目采购员岗位职责
2014/04/15 职场文书
农村党支部书记四风问题个人对照检查材料
2014/09/21 职场文书
群众路线四风问题整改措施
2014/09/27 职场文书
汽车机电维修工求职信
2014/09/30 职场文书
工伤私了协议书范本
2014/11/24 职场文书
2015年幼儿园卫生保健工作总结
2015/05/12 职场文书
Python开发五子棋小游戏
2022/04/28 Python