-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdsencrypt.py
More file actions
154 lines (128 loc) · 4.44 KB
/
dsencrypt.py
File metadata and controls
154 lines (128 loc) · 4.44 KB
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python2.7
# encoding:utf-8
# Created on 2017-02-15, by dozysun
import sys
import imp
import traceback
import marshal
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
ENCRYPT_START_STR = 'DSENCRYPT===:'
AES_RANDOM_KEY = 'sdfsdfssdfjsdoiewrjsdioafjlekjw'
AES_RANDOM_IV = '\x0f\xe1\x0c\x87Na\xa1D\x86$Z\x155\x8e\x82\x80' #Random.new().read(AES.block_size)
class DSImportHook(object):
"""
use imp module to make find and load module
see doc: https://docs.python.org/2/library/imp.html#imp.find_module
"""
def __init__(self):
self._modules = {}
self.aes_cipher = AESCipher()
def register_module(self, name, pathname, description, is_package=False):
self._modules[name] = (pathname, description, is_package)
def find_module(self, name, path=None):
try:
full_name = name
if '.' in name: # imp.find_module can't work with dot
if not path:
return None
name = name.rpartition('.')[-1]
f, pathname, description = imp.find_module(name, path)
if f:
if description[0].startswith('.py') and self.aes_cipher.is_encrypt_py(f):
self.register_module(full_name, pathname, description)
return self
except ImportError,e:
pass
else:
if f:
f.close()
return None
def load_module(self, name):
if name in sys.modules:
return sys.modules[name]
if name not in self._modules:
raise ImportError
try:
pathname, description, is_package = self._modules[name]
code = self.get_code(pathname)
ispkg = is_package
if ispkg:
code = marshal.loads(code[8:])
else:
if pathname.endswith(('pyc', 'pyo')):
code = marshal.loads(code[8:])
mod = sys.modules.setdefault(name, imp.new_module(name))
mod.__name__ = name
mod.__file__ = pathname
mod.__loader__ = self
if ispkg:
mod.__path__ = []
mod.__package__ = name
else:
mod.__package__ = name.rpartition('.')[0]
exec(code, mod.__dict__)
return mod
except Exception:
traceback.print_exc()
raise ImportError
def get_code(self, pathname):
f = open(pathname)
return self.decrypt_py(f.read())
def decrypt_py(self, code_str):
return self.aes_cipher.decrypt(code_str.replace(ENCRYPT_START_STR, '', 1))
def is_package(self, name):
return False
# return self._modules[name][-1][0] and False or True
class AESCipher(object):
def __init__(self, key=AES_RANDOM_KEY, iv=AES_RANDOM_IV):
self.bs = 32
self.key = hashlib.sha256(key.encode()).digest()
self.iv = iv
self.cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# def encrypt(self, raw):
# raw = self._pad(raw)
# return base64.b64encode(self.cipher.encrypt(raw))
#
# def decrypt(self, enc):
# return self._unpad(self.cipher.decrypt(base64.b64decode(enc)))
#
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:]))
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def is_encrypt_py(f):
if isinstance(f, file):
f = f.read(20)
if f.startswith(ENCRYPT_START_STR):
return True
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
aes_cipher = AESCipher()
def encrypt_file(file_):
if file_.endswith('pyc'):
mod = 'rb+'
else:
mod = 'r+'
with open(file_, mod) as f:
s = f.read()
if aes_cipher.is_encrypt_py(s):
return
with open(file_, 'w') as f:
es = aes_cipher.encrypt(s)
f.write(ENCRYPT_START_STR)
f.write(es)
if __name__ == '__main__':
sys.meta_path.insert(0, DSImportHook())