如何用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 相关文章推荐
在Django的模型和公用函数中使用惰性翻译对象
Jul 27 Python
基于Python实现一个简单的银行转账操作
Mar 06 Python
Python学习教程之常用的内置函数大全
Jul 14 Python
windows下cx_Freeze生成Python可执行程序的详细步骤
Oct 09 Python
用Python批量把文件复制到另一个文件夹的实现方法
Aug 16 Python
利用python、tensorflow、opencv、pyqt5实现人脸实时签到系统
Sep 25 Python
python双端队列原理、实现与使用方法分析
Nov 27 Python
Python计算机视觉里的IOU计算实例
Jan 17 Python
jupyter note 实现将数据保存为word
Apr 14 Python
Python基于paramunittest模块实现excl参数化
Apr 26 Python
python能在浏览器能运行吗
Jun 17 Python
PyQt5 QThread倒计时功能的实现代码
Apr 02 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
PHP5 操作MySQL数据库基础代码
2009/09/29 PHP
PHP5.3.1 不再支持ISAPI
2010/01/08 PHP
php的字符串用法小结
2010/06/08 PHP
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
2012/05/29 PHP
Prototype Date对象 学习
2009/07/12 Javascript
JavaScript(js)设置默认输入焦点(focus)
2012/12/28 Javascript
cookie 最近浏览记录(中文escape转码)具体实现
2013/06/08 Javascript
zTree插件之单选下拉菜单实例代码
2013/11/07 Javascript
js实现幻灯片播放图片示例代码
2013/11/07 Javascript
js实现顶部可折叠的菜单工具栏效果实例
2015/05/09 Javascript
javascript运动框架用法实例分析(实现放大与缩小效果)
2016/01/08 Javascript
AngularJS入门教程之表格实例详解
2016/07/27 Javascript
Vuex的初探与实战小结
2018/11/26 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
python 参数列表中的self 显式不等于冗余
2008/12/01 Python
python用字典统计单词或汉字词个数示例
2014/04/22 Python
Python学习教程之常用的内置函数大全
2017/07/14 Python
python使用正则表达式的search()函数实现指定位置搜索功能
2017/11/10 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
2018/11/07 Python
一步步教你用python的scrapy编写一个爬虫
2019/04/17 Python
Pycharm保存不能自动同步到远程服务器的解决方法
2019/06/27 Python
Python利用Xpath选择器爬取京东网商品信息
2020/06/01 Python
标签和贴纸印刷:Lightning Labels
2018/03/22 全球购物
英国健康和美容技术产品购物网站:CurrentBody
2019/07/17 全球购物
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
护士自我鉴定
2013/10/23 职场文书
感恩节红领巾广播稿
2014/02/11 职场文书
幼儿园元旦活动感言
2014/03/02 职场文书
药品业务员岗位职责
2014/04/17 职场文书
单位委托书怎么写
2014/08/02 职场文书
2015年党员岗位承诺书
2015/04/27 职场文书
Python 如何安装Selenium
2021/05/06 Python
JavaScript实现简单拖拽效果
2021/09/15 Javascript
我国拿下天问一号火星着陆区附近 22 个地理实体命名:平乐、西柏坡、古田、漠河等
2022/04/29 数码科技
详解flex:1什么意思
2022/07/23 HTML / CSS