如何用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的Tornado框架对子域名和泛域名的支持
May 02 Python
Python实现一个Git日志统计分析的小工具
Dec 14 Python
Python列表推导式与生成器表达式用法示例
Feb 08 Python
mac 安装python网络请求包requests方法
Jun 13 Python
解决Tensorflow使用pip安装后没有model目录的问题
Jun 13 Python
修复 Django migration 时遇到的问题解决
Jun 14 Python
在cmder下安装ipython以及环境的搭建
Oct 19 Python
Python爬虫实现获取动态gif格式搞笑图片的方法示例
Dec 24 Python
python实现集中式的病毒扫描功能详解
Jul 09 Python
Python爬虫实现HTTP网络请求多种实现方式
Jun 19 Python
Python语言编写智力问答小游戏功能
Oct 13 Python
从Pytorch模型pth文件中读取参数成numpy矩阵的操作
Mar 04 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
配置Apache2.2+PHP5+CakePHP1.2+MySQL5运行环境
2009/04/25 PHP
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
Yii入门教程之Yii安装及hello world
2014/11/25 PHP
解读PHP中的垃圾回收机制
2015/08/10 PHP
php中preg_match的isU代表什么意思
2015/10/01 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
php微信公众号开发之校园图书馆
2018/10/20 PHP
任意位置显示html菜单
2007/02/01 Javascript
查询绑定数据岛的表格中的文本并修改显示方式的js代码
2009/12/15 Javascript
使用JQuery和CSS模拟超链接的用户单击事件的实现代码
2012/05/23 Javascript
js 获取、清空input type="file"的值(示例代码)
2013/12/24 Javascript
jQuery ajax调用WCF服务实例
2014/07/16 Javascript
jQuery的one()方法用法实例
2015/01/19 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
2015/09/27 Javascript
在Javascript操作JSON对象,增加 删除 修改的简单实现
2016/06/02 Javascript
jQuery 3 中的新增功能汇总介绍
2016/06/12 Javascript
微信小程序新增的拖动组件movable-view使用教程
2017/05/20 Javascript
深入理解ES6学习笔记之块级作用域绑定
2017/08/19 Javascript
Django使用多数据库的方法
2017/09/06 Javascript
Vue实战教程之仿肯德基宅急送App
2019/07/19 Javascript
教你如何用Node实现API的转发(某音乐)
2019/09/20 Javascript
理解python正则表达式
2016/01/15 Python
python判断一个集合是否为另一个集合的子集方法
2018/05/04 Python
10分钟教你用Python实现微信自动回复功能
2018/11/28 Python
python实现在遍历列表时,直接对dict元素增加字段的方法
2019/01/15 Python
python SVD压缩图像的实现代码
2019/11/05 Python
python使用Word2Vec进行情感分析解析
2020/07/31 Python
在Python中字典按值排序的实现方法
2020/11/12 Python
python与idea的集成的实现
2020/11/20 Python
CSS去掉A标签(链接)虚线框的方法
2014/04/01 HTML / CSS
HTML5中的音频和视频媒体播放元素小结
2016/01/29 HTML / CSS
美国大型的健身社区和补充商店:Bodybuilding.com
2016/09/06 全球购物
毕业生自荐书
2014/02/02 职场文书
合伙开公司协议书范本
2014/10/28 职场文书
表扬稿范文
2015/01/17 职场文书
导游词之南京莫愁湖公园
2019/11/13 职场文书