如何用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通过urllib2获取带有中文参数url内容的方法
Mar 13 Python
Python实现简单的代理服务器
Jul 25 Python
举例详解Python中yield生成器的用法
Aug 05 Python
Python 中的with关键字使用详解
Sep 11 Python
基于Python闭包及其作用域详解
Aug 28 Python
python爬取各类文档方法归类汇总
Mar 22 Python
python 处理dataframe中的时间字段方法
Apr 10 Python
对pandas通过索引提取dataframe的行方法详解
Feb 01 Python
Spring Cloud Feign高级应用实例详解
Dec 10 Python
Django多数据库联用实现方法解析
Nov 12 Python
python RSA加密的示例
Dec 09 Python
Python使用Kubernetes API访问集群
May 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
Win2003服务器安全加固设置--进一步提高服务器安全性
2007/05/23 PHP
php的大小写敏感问题整理
2011/12/29 PHP
php商品对比功能代码分享
2015/09/24 PHP
c#和Javascript操作同一json对象的实现代码
2012/01/17 Javascript
JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现
2012/08/14 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
JavaScript html5 canvas画布中删除一个块区域的方法
2016/01/26 Javascript
javascript实现圣旨卷轴展开效果(代码分享)
2017/03/23 Javascript
利用JavaScript在网页实现八数码启发式A*算法动画效果
2017/04/16 Javascript
javascript编写简易计算器
2017/05/06 Javascript
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
AngularJS 事件发布机制
2018/08/28 Javascript
NodeJs入门教程之定时器和队列
2019/03/08 NodeJs
解决vue.js提交数组时出现数组下标的问题
2019/11/05 Javascript
javascript实现获取中文汉字拼音首字母
2020/05/19 Javascript
python搭建简易服务器分析与实现
2012/12/15 Python
浅谈Python中函数的参数传递
2016/06/21 Python
Python基于回溯法子集树模板解决取物搭配问题实例
2017/09/02 Python
[原创]pip和pygal的安装实例教程
2017/12/07 Python
Python实现繁?转为简体的方法示例
2018/12/18 Python
利用Python+阿里云实现DDNS动态域名解析的方法
2019/04/01 Python
python pygame实现球球大作战
2019/11/25 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
2020/02/28 Python
安装多个版本的TensorFlow的方法步骤
2020/04/21 Python
Infababy英国:婴儿推车、Travel System婴儿车和婴儿汽车座椅销售
2018/05/23 全球购物
Farfetch巴西官网:奢侈品牌时尚购物平台
2020/10/19 全球购物
c/c++某大公司的两道笔试题
2014/02/02 面试题
出国留学自荐信
2013/10/25 职场文书
客服专员岗位职责
2014/02/28 职场文书
小学生操行评语
2014/04/22 职场文书
实习推荐信
2014/05/10 职场文书
收款委托书范本
2014/09/11 职场文书
2015年度招聘工作总结
2015/05/28 职场文书
python实现过滤敏感词
2021/05/08 Python
Vue实现动态查询规则生成组件
2021/05/27 Vue.js
详解Python中的进程和线程
2021/06/23 Python