第三节课:加密文件

本贴最后更新于 1540 天前,其中的信息可能已经事过景迁

上一节课我们学习了python操作文件,本节课就使用python来加密文件。

文件本质上就是一个字节串,所有加密方法都是围绕着这些字节串来操作的。

今天我们使用的方法严格上来说不是加密,但是能够满足日常使用了,切原理相对简单易懂。

文本文件加密

加密解密思路

文字是以字符编码中的编码数字的二进制数存储在电脑中的。

通过给每个字符一个固定的偏移量使原来的字符偏移为其他字符达到加密的效果。

解密时再依次偏移回来即可。

# 例如 中 字的unicode是 20013
ord('中')

20013

# 向后偏移10个字是 '丷'
chr(20013+10)

'丷'
在当前目录abc.txt文件中有你写给你暗恋的女生的情书,内容如下:

我坦白,我交待,我很坏,我无赖,偷过蔡家的梨,摸过李家的菜,不求党的宽恕,不想zf的宽待,只要你的爱!

现在使用刚才的思路加密它。

with open('abc.txt', 'r+', encoding='utf-8') as f:
    content = f.read()
    f.seek(0) # 跳转到文件开始
    # 循环每个字
    for c in content:
        f.write(chr(ord(c)+10))

加密后的内容为:

戛坰皇6戛亮徏6戛徒坙6戛旪赠6傁近蔫寀皎梲6撂近杘寀皎菦6丗汌兤皎寇恟6丗惽敉度皎寇徏6叴見佪皎爻+

效果还不错。

接下来再解密它

with open('abc.txt', 'r+', encoding='utf-8') as f:
    content = f.read()
    f.seek(0) # 跳转到文件开始
    # 循环每个字
    for c in content:
        f.write(chr(ord(c)-10))

偏移的值大家可以自行设定。

代码

将上面的加解密封装为函数如下:

def text_encrypt(filename):
    """
    文本文件加密
    :param filename:
    :return:
    """
    try:
        f = open(filename, 'r+', encoding='gbk')
        content = f.read()
    except UnicodeDecodeError as e:
        f = open(filename, 'r+', encoding='utf-8')
        content = f.read()
    f.seek(0)
    for c in content:
        f.write(chr(ord(c)+10))
    print('加密文件{}成功!'.format(filename))
def text_decrypt(filename):
    """
    文本文件解密
    :param filename:
    :return:
    """
    try:
        f = open(filename, 'r+', encoding='gbk')
        content = f.read()
    except UnicodeDecodeError as e:
        f = open(filename, 'r+', encoding='utf-8')
        content = f.read()

    f.seek(0)
    for c in content:
        f.write(chr(ord(c)-10))
    print('解密文件{}成功!'.format(filename))

二进制文件加密

加密解密思路

二进制文件往往会比较大,比如视频等,如过对每个字节进行操作速度较慢,且内存占用也较大。

二进制文件往往有特殊的编码,文件有少许字节更改就会破坏编码。

所以加密思路为将二进制文件前后相同大小的字节内容进行调换达到破坏源文件形成加密的效果。

解密时,再还原文件。

当前目录下有你的果照一张gz.jpg,你舍不得删又怕别人看,使用上面的思路加密一下。

with open('gz.jpg', 'rb+') as f:
    # 读取前10字节
    first = f.read(10)
    # 跳到文件末尾前10字节
    f.seek(-10,2)
    # 读取结尾的10字节
    last = f.read()
    # 跳到开头
    f.seek(0)
    # 将末尾的10字节写到开头
    f.write(last)
    # 跳到文件末尾前10字节
    f.seek(-10,2)
    # 将前10字节内容替换末尾10字节
    f.write(first)

运行后果然发现打不开了
image.png

哪一天你又想欣赏一下自己的美态,再次运行上面的代码即可以解密。

代码

将上面的加解密封装为函数如下:

def bytes_encrypt(filename):
    with open(filename, 'rb+') as f:
        first = f.read(10)
        f.seek(-10, 2)
        last = f.read()
        f.seek(0)
        f.write(last)
        f.seek(-10, 2)
        f.write(first)

整合

上面的代码只能一个文件一个文件的加密,我们整合它们,使用命令行的方式来运行脚本,达到既可以加密单个文件又可以加密多个文件的功能。

思路

main函数流程
image.png

加密解密函数流程
image.png

代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# @Time    : 2020/8/21 4:23 下午
# @Author  : xinlan
import sys
import os


def is_text(filename):
    """
    判断文件是否文本文件
    :param filename:
    :return:
    """
    suffix = ['txt', 'text', 'py']
    if filename.split('.')[-1] in suffix:
        return True
    else:
        return False


def text_encrypt(filename):
    """
    文本文件加密
    :param filename:
    :return:
    """
    try:
        f = open(filename, 'r+', encoding='gbk')
        content = f.read()
    except UnicodeDecodeError as e:
        f = open(filename, 'r+', encoding='utf-8')
        content = f.read()

    f.seek(0)
    for c in content:
        f.write(chr(ord(c) + 10))
    print('加密文件{}成功!'.format(filename))


def text_decrypt(filename):
    """
    文本文件解密
    :param filename:
    :return:
    """
    try:
        f = open(filename, 'r+', encoding='gbk')
        content = f.read()
    except UnicodeDecodeError as e:
        f = open(filename, 'r+', encoding='utf-8')
        content = f.read()

    f.seek(0)
    for c in content:
        f.write(chr(ord(c)-10))
    print('解密文件{}成功!'.format(filename))


def bytes_encrypt(filename):
    with open(filename, 'rb+') as f:
        first = f.read(10)
        f.seek(-10, 2)
        last = f.read()
        f.seek(0)
        f.write(last)
        f.seek(-10, 2)
        f.write(first)


def encrypt(filename):
    """
    加密文件
    :param filename:
    :return:
    """
    if is_text(filename):
        text_encrypt(filename)
    else:
        bytes_encrypt(filename)
        print('加密文件{}成功!'.format(filename))


def decrypt(filename):
    """
    解密文件
    :param filename:
    :return:
    """
    if is_text(filename):
        text_decrypt(filename)
    else:
        bytes_encrypt(filename)
    print('解密文件{}成功!'.format(filename))


def get_file_list(path):
    for root, dirs, files in os.walk(path):
        return [os.path.join(root, f) for f in files]


def main():
    try:
        _, t, path = sys.argv

    except Exception as e:
        exit('请输入正确的参数')

    if t == 'e':
        if os.path.isdir(path):
            # 加密当前文件夹下所有文件
            files = get_file_list(path)
            for file in files:
                encrypt(file)
        else:
            # 加密文件
            encrypt(path)
    elif t == 'd':
        # 解密
        if os.path.isdir(path):
            # 解密当前文件加下所有文件
            files = get_file_list(path)
            for file in files:
                decrypt(file)
        else:
            # 解密文件
            decrypt(path)
    else:
        print('请输入正确的参数')


if __name__ == '__main__':

    main()

将上面的代码保存到encrypt.py脚本中,然后通过命令

python encrypt.py e 文件/文件夹

加密文件或文件夹中的所有文件。

通过命令:

python encrypt.py d 文件/文件夹

解密文件或文件夹中的所有文件

回帖
请输入回帖内容 ...