如何用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中__init__.py文件的作用详解
Sep 18 Python
Python使用sftp实现上传和下载功能(实例代码)
Mar 14 Python
python初学之用户登录的实现过程(实例讲解)
Dec 23 Python
Python字典循环添加一键多值的用法实例
Jan 20 Python
对IPython交互模式下的退出方法详解
Feb 16 Python
Python hexstring-list-str之间的转换方法
Jun 12 Python
Python3批量生成带logo的二维码方法
Jun 24 Python
python实现倒计时小工具
Jul 29 Python
深入浅析python变量加逗号,的含义
Feb 22 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 Python
Python序列化与反序列化相关知识总结
Jun 08 Python
python脚本框架webpy模板控制结构
Nov 20 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实现图片简单上传
2006/10/09 PHP
PHP COOKIE设置为浏览器进程
2009/06/21 PHP
PHP优于Node.js的五大理由分享
2012/09/15 PHP
探讨PHP删除文件夹的三种方法
2013/06/09 PHP
设置php页面编码的两种方法示例介绍
2014/03/03 PHP
PHP中file_exists函数不支持中文名的解决方法
2014/07/26 PHP
php中Ctype函数用法详解
2014/12/09 PHP
php中strlen和mb_strlen用法实例分析
2016/11/12 PHP
laravel 根据不同组织加载不同视图的实现
2019/10/14 PHP
htm调用JS代码
2007/03/15 Javascript
使用prototype.js 的时候应该特别注意的几个问题.
2007/04/12 Javascript
javascript 一个函数对同一元素的多个事件响应
2009/07/25 Javascript
JS高级笔记
2011/07/13 Javascript
jQuery代码优化 遍历篇
2011/11/01 Javascript
js如何获取object类型里的键值
2014/02/18 Javascript
JS中类或对象的定义说明
2014/03/10 Javascript
jQuery实现视频作为全屏幕背景
2014/12/18 Javascript
js中unicode转码方法详解
2015/10/09 Javascript
AngularJs Understanding the Model Component
2016/09/02 Javascript
KnockoutJS 3.X API 第四章之表单value绑定
2016/10/10 Javascript
JS实现的按钮点击颜色切换功能示例
2017/10/19 Javascript
react实现换肤功能的示例代码
2018/08/14 Javascript
Python读取word文本操作详解
2018/01/22 Python
Python即时网络爬虫项目启动说明详解
2018/02/23 Python
python读取xlsx的方法
2018/12/25 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
HTML5时代CSS设置漂亮字体取代图片
2014/09/04 HTML / CSS
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
司仪主持词两篇
2014/03/22 职场文书
竞选文艺委员演讲稿
2014/04/28 职场文书
学校党支部承诺书
2015/04/30 职场文书
酒会开场白大全
2015/06/01 职场文书
爱护环境建议书
2015/09/14 职场文书
教您怎么制定西餐厅运营方案 ?
2019/07/05 职场文书
C站最全Python标准库总结,你想要的都在这里
2021/07/03 Python
golang三种设计模式之简单工厂、方法工厂和抽象工厂
2022/04/10 Golang