如何用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使用在线API查询IP对应的地理位置信息实例
Jun 01 Python
Python中让MySQL查询结果返回字典类型的方法
Aug 22 Python
在Python中使用Neo4j数据库的教程
Apr 16 Python
Python实现的爬虫功能代码
Jun 24 Python
Python 基础教程之闭包的使用方法
Sep 29 Python
python实现搜索文本文件内容脚本
Jun 22 Python
python pickle存储、读取大数据量列表、字典数据的方法
Jul 07 Python
TensorFlow 多元函数的极值实例
Feb 10 Python
Python函数默认参数常见问题及解决方案
Mar 26 Python
DRF框架API版本管理实现方法解析
Aug 21 Python
python re的findall和finditer的区别详解
Nov 15 Python
Python爬虫自动化获取华图和粉笔网站的错题(推荐)
Jan 08 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
PHP 正则表达式常用函数
2014/08/17 PHP
PHP实现通过二维数组键值获取一维键名操作示例
2019/10/11 PHP
jQuery实现列表自动循环滚动鼠标悬停时停止滚动
2013/09/06 Javascript
点击弹出层效果&弹出窗口后网页背景变暗效果的实现代码
2014/02/10 Javascript
JavaScript的21条基本知识点
2014/03/04 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
jquery操作angularjs对象
2015/06/26 Javascript
javascript图片预加载完整实例
2015/12/10 Javascript
Javascript获取数组中的最大值和最小值的方法汇总
2016/01/01 Javascript
javascript HTML5 Canvas实现圆盘抽奖功能
2016/04/11 Javascript
小白谈谈对JS原型链的理解
2016/05/03 Javascript
探讨AngularJs中ui.route的简单应用
2016/11/16 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
解决bootstrap-select 动态加载数据不显示的问题
2018/08/10 Javascript
Bootstrap的aria-label和aria-labelledby属性实例详解
2018/11/02 Javascript
Vue+Koa2 打包后进行线上部署的教程详解
2019/07/31 Javascript
js判断复选框是否选中的方法示例【基于jQuery】
2019/10/10 jQuery
优化Vue中date format的性能详解
2020/01/13 Javascript
微信小程序实现选项卡滑动切换
2020/10/22 Javascript
Python3 伪装浏览器的方法示例
2017/11/23 Python
zookeeper python接口实例详解
2018/01/18 Python
基于python的图片修复程序(实现水印去除)
2018/06/04 Python
python3+django2开发一个简单的人员管理系统过程详解
2019/07/23 Python
python 追踪except信息方式
2020/04/25 Python
html5 css3 动态气泡按钮实例演示
2012/12/02 HTML / CSS
HTML5 LocalStorage 本地存储刷新值还在
2017/03/10 HTML / CSS
美国最大的高尔夫发球时间预订网站:TeeOff.com
2018/03/28 全球购物
Stuarts London美国/加拿大:世界领先的独立男装零售商之一
2019/03/18 全球购物
不用游标的SQL语句有哪些
2012/09/07 面试题
酒店公关部经理岗位职责
2013/11/24 职场文书
2014春晚主持词
2014/03/25 职场文书
团代会开幕词
2015/01/28 职场文书
CSS极坐标的实例代码
2021/06/03 HTML / CSS
Python通过loop.run_in_executor执行同步代码 同步变为异步
2022/04/11 Python
利用Python实现翻译HTML中的文本字符串
2022/06/21 Python
HTML页面点击按钮关闭页面的多种方式
2022/12/24 HTML / CSS