如何用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实现将excel文件转化成CSV格式
Mar 22 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
Apr 02 Python
DataFrame中的object转换成float的方法
Apr 10 Python
Python实现压缩文件夹与解压缩zip文件的方法
Sep 01 Python
详解python项目实战:模拟登陆CSDN
Apr 04 Python
python找出因数与质因数的方法
Jul 25 Python
python实现网站用户名密码自动登录功能
Aug 09 Python
python实现两个文件夹的同步
Aug 29 Python
基于python实现把图片转换成素描
Nov 13 Python
python利用JMeter测试Tornado的多线程
Jan 12 Python
Python使用tkinter实现摇骰子小游戏功能的代码
Jul 02 Python
Python MNIST手写体识别详解与试练
Nov 07 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
Yii视图CGridView实现操作按钮定义地址示例
2016/07/14 PHP
thinkPHP框架中layer.js的封装与使用方法示例
2019/01/18 PHP
PHP中define() 与 const定义常量的区别详解
2019/06/25 PHP
js 对象是否存在判断
2009/07/15 Javascript
javascript学习笔记(十) js对象 继承
2012/06/19 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
jQuery通过点击行来删除HTML表格行的实现示例
2014/09/10 Javascript
jQuery创建DOM元素实例解析
2015/01/19 Javascript
jQuery css() 方法动态修改CSS属性
2016/09/25 Javascript
jQuery插件jquery.kxbdmarquee.js实现无缝滚动效果
2017/02/15 Javascript
JS控制鼠标拒绝点击某一按钮的实例
2017/12/29 Javascript
5 种JavaScript编码规范
2018/01/30 Javascript
[47:55]Ti4第二日主赛事败者组 NaVi vs EG 1
2014/07/20 DOTA
[07:49]2014DOTA2国际邀请赛 Newbee夺冠后采访xiao8坦言奖金会上交
2014/07/23 DOTA
[50:50]完美世界DOTA2联赛PWL S3 Galaxy Racer vs Phoenix 第一场 12.10
2020/12/13 DOTA
在Python中使用base64模块处理字符编码的教程
2015/04/28 Python
基于Python的XSS测试工具XSStrike使用方法
2017/07/29 Python
简单实现python聊天程序
2018/04/01 Python
浅谈python中str字符串和unicode对象字符串的拼接问题
2018/12/04 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
2019/08/20 Python
将matplotlib绘图嵌入pyqt的方法示例
2020/01/08 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
2020/02/21 Python
Roxy美国官网:澳大利亚冲浪、滑雪健身品牌
2016/07/30 全球购物
英国网上自行车商店:Tredz Bikes
2019/10/29 全球购物
婚假请假条格式及范文
2014/04/10 职场文书
节能环保口号
2014/06/12 职场文书
应届生找工作求职信
2014/06/24 职场文书
毕业实习自我鉴定范文2014
2014/09/26 职场文书
工作检讨书500字
2014/10/19 职场文书
乡镇干部学习心得体会
2016/01/23 职场文书
HR必备:销售经理聘用合同范本
2019/08/21 职场文书
Nginx解决前端访问资源跨域问题的方法详解
2021/03/31 Servers
node快速搭建后台的实现步骤
2022/02/18 NodeJs
pandas中pd.groupby()的用法详解
2022/06/16 Python