Python文本及脚本加密

Python脚本实现异或方法加密和解密文本文件,通过Cython编译为so文件加密Python脚本

文本加密和解密

异或是一种简单的加密算法,根据异或的运算规则,通过密钥对明文信息进行异或运算,可以得到加密后的密文信息。
同时由于异或运算的可逆性,用同一密钥对密文信息再次进行异或运算,可以得到明文信息。

Python实现

以下是对文本文件异或加密及解密的Python实现,Encrypt_Decrypt_Text.py。
此脚本里设定的字符编码是UTF-8,可以按需修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Python
# Encrypt or decrypt text file with a password
# coding=utf-8

import os
import sys

EncodeSet = "UTF-8"

def encrypt(String, Password, Seed):
if (len(Password) == 0):
sys.stderr.write("Password can't be empty. Exit.")
exit()
Key_Int = ord(Password[Seed % len(Password)])
String_Byte = String.encode(EncodeSet)
String_Int = int.from_bytes(String_Byte, 'big')
String_Encrypt = String_Int ^ Key_Int
return String_Encrypt

def decrypt(String, Password, Seed):
if (len(Password) == 0):
sys.stderr.write("Password can't be empty. Exit.")
exit()
Key_Int = ord(Password[Seed % len(Password)])
String_Decrypt = String ^ Key_Int
Length = (String_Decrypt.bit_length() + 7) // 8
Decrypt_Byte = int.to_bytes(String_Decrypt, Length, 'big')
Decrypt = Decrypt_Byte.decode(EncodeSet)
return Decrypt

def encrypt_file(Input, Password):
Input = os.path.abspath(Input)
Encrypt_Output_File = Input + ".encrypt"
Input_File = open(Input, "rt", encoding = EncodeSet)
Output_File = open(Encrypt_Output_File, "wt", encoding = EncodeSet)
Counter = 0
for Line in Input_File:
Counter = Counter + 1
Line = Line.strip("\r").strip("\n")
for Word in Line:
Word_Encrypt = encrypt(Word, Password, Counter)
Output_File.write(str(Word_Encrypt) + " ")
Output_File.write("\n")
Input_File.close()
Output_File.close()
return Encrypt_Output_File

def decrypt_file(Input, Password):
Input = os.path.abspath(Input)
Decrypt_String = ""
Input_File = open(Input, "rt", encoding = EncodeSet)
Counter = 0
for Line in Input_File:
Counter = Counter + 1
Line = Line.strip("\r").strip("\n")
Line = Line.strip(" ")
for Word in Line.split(" "):
Word_Decrypt = decrypt(int(Word), Password, Counter)
Decrypt_String = Decrypt_String + Word_Decrypt
Decrypt_String = Decrypt_String + "\n"
Input_File.close()
Decrypt_String = Decrypt_String.strip("\r").strip("\n")
return Decrypt_String

使用示例

加密

以下是加密脚本示例,Encrypt.py。
encrypt_file函数返回的是加密文件路径,路径是[原文件路径].encrypt。

1
2
3
4
5
6
7
8
9
10
11
12
# Python
# -*- coding:utf-8 -*-

import Encrypt_Decrypt_Text
import sys

Input = sys.argv[1]
Password = sys.argv[2]

Encrypt_File_Path = Encrypt_Decrypt_Text.encrypt_file(Input, Password)

print(Encrypt_File_Path)

解密

以下是解密脚本示例,Decrypt.py。
函数返回解密后的字符串,建议在脚本中解密后直接调用字符串,不要重新保存成文件。
假如密码错误,会报错或返回乱码。

1
2
3
4
5
6
7
8
9
10
11
12
# Python
# -*- coding:utf-8 -*-

import Encrypt_Decrypt_Text
import sys

Input = sys.argv[1]
Password = sys.argv[2]

Decrype_File_Content = Encrypt_Decrypt_Text.decrypt_file(Input, Password)

print(Decrype_File_Content)

脚本加密

用于文本文件加密的密钥,如果以明文方式写在脚本里等于没有加密。
所以需要对调用解密过程的python脚本再通过Cython加密,那么脚本里密钥的也加密了。

安装Cython

1
2
# Python
python -m pip install Cython

Cython脚本

以下是将python脚本编译为so文件的脚本,Cpython_so.py。
以下脚本会生成so文件和清理中间文件,调用此脚本方法见”调用Cython脚本”部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# Python

import sys
import os
import re
import argparse

############################################################## Help #############################################################

parser=argparse.ArgumentParser(
description="Description: Generate .so from .py. Version of .so is base of python version.",
prog="Cpython_so.py",
usage="python Cpython_so.py [-h] [-V] -i <python script> -o <Output Dir>",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-V','--version',action="version",version="Version 1.0.0")
parser.add_argument('-i','--input',required=True,type=str,help="File: python script")
parser.add_argument('-o','--output_dir',required=True,type=str,help="Dir: Output directory path")
if len(sys.argv[1:]) == 0:
parser.print_help()
parser.exit()
args=parser.parse_args()

############################################################## Run ##############################################################

Input_Dir = os.path.dirname(os.path.abspath(args.input))
Output_Dir = os.path.abspath(args.output_dir)
if (Input_Dir == Output_Dir):
sys.stderr.write("Output directory can't be same as python script. Exit.\n")
exit(1)

if not (os.path.exists(args.output_dir)):
os.mkdir(args.output_dir)

Module = re.sub(".py$", "", os.path.basename(args.input))

# Copy Original Script To Work Dir
Py_Script = os.path.abspath(args.output_dir) + "/" + os.path.basename(args.input)
Command_Cp = "cp " + args.input + " " + Py_Script
os.system(Command_Cp)

# Generate .so From .py
Cpython_Script = os.path.abspath(args.output_dir) + "/Cpython_Setup.py"
Cpython_Script_File = open(Cpython_Script, "w")
Cpython_Script_File.write("from distutils.core import setup" + "\n")
Cpython_Script_File.write("from Cython.Build import cythonize" + "\n")
Cpython_Script_File.write("" + "\n")
Cpython_Script_File.write("setup(ext_modules = cythonize(\"" + Py_Script + "\"))" + "\n")
Cpython_Script_File.write("" + "\n")
Cpython_Script_File.close()

Py_Version = "python" + ".".join([str(sys.version_info[0]),str(sys.version_info[1])])
Command_Cpython = Py_Version + " " + Cpython_Script + " build_ext --inplace"
os.system(Command_Cpython)

# Move Result .so And Clean Temp Dir
So_File = os.getcwd() + "/" + Module + "*.so"
C_File = os.path.abspath(args.output_dir) + "/" + Module + ".c"
Temp_Dir = os.getcwd() + "/" + "build"

Command_Move = "mv " + So_File + " " + os.path.abspath(args.output_dir)
os.system(Command_Move)

Commad_Clean = "rm -rf " + " ".join([Py_Script, Cpython_Script, Temp_Dir, C_File])
os.system(Commad_Clean)

# Generate .py And .sh To Run .so
So_Py_Script = os.path.abspath(args.output_dir) + "/" + Module + ".py"
So_Sh_Script = os.path.abspath(args.output_dir) + "/" + Module + ".sh"

So_Py_Script_File = open(So_Py_Script, "w")
So_Py_Script_File.write("import " + Module + "\n\n")
So_Py_Script_File.close()

So_Sh_Script_File = open(So_Sh_Script, "w")
So_Sh_Script_File.write(Py_Version + " " + So_Py_Script + "\n")
So_Sh_Script_File.close()

Command_Chmod = "chmod +x " + So_Py_Script + " " + So_Sh_Script
os.system(Command_Chmod)

调用Cython脚本

可以写个shell调用,也可以直接命令行调用。
-i 是待加密的python脚本路径,-o 是加密后脚本的输出目录路径。
不同Python版本加密生成的so文件不一定通用,加密前脚本用哪个Python版本调用,就用哪个版本调用Cython脚本。
加密后的.so文件可以作为模块调用,使用方法可参考输出目录生成的.sh文件。

1
2
3
4
5
6
7
# Shell

# 系统默认的Python版本
python Cpython_so.py -i ../../Cpython_Setup/Step1_Python_To_so/Store_Tumor_Report.py -o ./Test_2.7

# 指定用Python 3.6版本
python3.6 Cpython_so.py -i ../../Cpython_Setup/Step1_Python_To_so/Store_Tumor_Report.py -o ./Test_3.6

参考资料

  1. 异或加密(XOR)原理及实现
  2. Python 循环异或对文件进行加解密
  3. Python程序加密-cython