如何用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实现实例
Apr 26 Python
详解Python3.1版本带来的核心变化
Apr 07 Python
Django中对通过测试的用户进行限制访问的方法
Jul 23 Python
使用Python简单的实现树莓派的WEB控制
Feb 18 Python
利用Python中的pandas库对cdn日志进行分析详解
Mar 07 Python
Python 装饰器深入理解
Mar 16 Python
深入理解Django自定义信号(signals)
Oct 15 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
Apr 01 Python
django 邮件发送模块smtp使用详解
Jul 22 Python
Python绘制热力图示例
Sep 27 Python
python中判断文件结束符的具体方法
Aug 04 Python
python读取excel数据绘制简单曲线图的完整步骤记录
Oct 30 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+MySQL5.0中文乱码解决方法
2006/11/20 PHP
PHP 5.0对象模型深度探索之类的静态成员
2008/03/27 PHP
php htmlentities()函数的定义和用法
2016/05/13 PHP
php版微信公众平台实现预约提交后发送email的方法
2016/09/26 PHP
php设计模式之职责链模式定义与用法经典示例
2019/09/19 PHP
在 Laravel 中动态隐藏 API 字段的方法
2019/10/25 PHP
jquery、js操作checkbox全选反选
2014/03/12 Javascript
对Web开发中前端框架与前端类库的一些思考
2015/03/27 Javascript
原生js和jquery实现图片轮播特效
2015/04/23 Javascript
JQuery实现动态添加删除评论的方法
2015/05/18 Javascript
JS实现仿QQ面板的手风琴效果折叠菜单代码
2015/09/11 Javascript
js随机生成26个大小写字母
2016/02/12 Javascript
谷歌showModalDialog()方法不兼容出现对话窗口的解决办法
2016/02/15 Javascript
详解Angular的内置过滤器和自定义过滤器【推荐】
2016/12/26 Javascript
正则验证小数点后面只能有两位数的方法
2017/02/28 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
2017/03/02 Javascript
Node.js如何响应Ajax的POST请求并且保存为JSON文件详解
2017/03/10 Javascript
validationEngine 表单验证插件使用实例代码
2017/06/15 Javascript
ES6新特性:使用export和import实现模块化详解
2017/07/31 Javascript
JS 自执行函数原理及用法
2019/08/05 Javascript
详解小程序BackgroundAudioManager踩坑之旅
2019/12/08 Javascript
python通过装饰器检查函数参数数据类型的方法
2015/03/13 Python
Python基于PycURL自动处理cookie的方法
2015/07/25 Python
Python中http请求方法库汇总
2016/01/06 Python
Python中函数参数设置及使用的学习笔记
2016/05/03 Python
python读取csv文件并把文件放入一个list中的实例讲解
2018/04/27 Python
详解python算法之冒泡排序
2019/03/05 Python
Ubuntu18.04安装 PyCharm并使用 Anaconda 管理的Python环境
2020/04/08 Python
golang/python实现归并排序实例代码
2020/08/30 Python
C语言怎样定义和声明全局变量和函数最好
2013/11/26 面试题
2014年流动人口工作总结
2014/11/26 职场文书
工作调动申请报告
2015/05/18 职场文书
篮球比赛通讯稿
2015/07/18 职场文书
公司周年庆典致辞
2015/07/30 职场文书
2016年情人节问候语
2015/11/11 职场文书
Python中22个万用公式的小结
2021/07/21 Python