如何用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 相关文章推荐
高性能web服务器框架Tornado简单实现restful接口及开发实例
Jul 16 Python
Python实现文件按照日期命名的方法
Jul 09 Python
Django卸载之后重新安装的方法
Mar 15 Python
python生成器,可迭代对象,迭代器区别和联系
Feb 04 Python
元组列表字典(莫烦python基础)
Apr 03 Python
Python 实例方法、类方法、静态方法的区别与作用
Aug 14 Python
python sorted函数的小练习及解答
Sep 18 Python
python 采用paramiko 远程执行命令及报错解决
Oct 21 Python
Python程序慢的重要原因
Sep 04 Python
Django admin组件的使用
Oct 24 Python
Numpy中的数组搜索中np.where方法详细介绍
Jan 08 Python
Pytorch如何切换 cpu和gpu的使用详解
Mar 01 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
crontab无法执行php的解决方法
2016/01/25 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
PHP设置images目录不充许http访问的方法
2016/11/01 PHP
PHP判断是手机端还是PC端 PHP判断是否是微信浏览器
2017/03/15 PHP
PHP检查端口是否可以被绑定的方法示例
2018/08/09 PHP
javascript实现的动态添加表单元素input,button等(appendChild)
2007/11/24 Javascript
收集的一些Array及String原型对象的扩展实现代码
2010/12/05 Javascript
JavaScript模拟实现键盘打字效果
2015/06/29 Javascript
loading动画特效小结
2017/01/22 Javascript
NodeJS基础API搭建服务器详细过程记录
2017/04/01 NodeJs
mac上node.js环境的安装测试
2017/07/03 Javascript
postman+json+springmvc测试批量添加实例
2018/03/31 Javascript
JavaScript 复制对象与Object.assign方法无法实现深复制
2018/11/02 Javascript
微信浏览器左上角返回按钮监听的实现
2020/03/04 Javascript
Vue CLI3移动端适配(px2rem或postcss-plugin-px2rem)
2020/04/27 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
Python中使用摄像头实现简单的延时摄影技术
2015/03/27 Python
用Python实现将一张图片分成9宫格的示例
2019/07/05 Python
python:按行读入,排序然后输出的方法
2019/07/20 Python
python KNN算法实现鸢尾花数据集分类
2019/10/24 Python
Pytorch模型转onnx模型实例
2020/01/15 Python
基于Tensorflow一维卷积用法详解
2020/05/22 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
Grow Gorgeous美国官网:只要八天,体验唤醒毛囊后新生的茂密秀发
2018/06/04 全球购物
学校安全工作制度
2014/01/19 职场文书
少先队入队活动方案
2014/02/08 职场文书
美术指导求职信
2014/03/17 职场文书
小学生竞选班干部演讲稿
2014/04/24 职场文书
法定代表人资格证明书
2014/09/11 职场文书
党委书记群众路线对照检查材料思想汇报
2014/10/04 职场文书
员工工作及收入证明
2014/10/28 职场文书
2014年设备管理工作总结
2014/11/26 职场文书
售后前台接待岗位职责
2015/04/03 职场文书
大学生违纪检讨书范文
2015/05/07 职场文书
2016秋季运动会前导词
2015/11/25 职场文书
MongoDB数据库之添删改查
2022/04/26 MongoDB