导入后从磁盘删除Python模块,同时将其保留在内存中?
我正在尝试对我正在进行的项目的一部分设置加密。现在,我正在尝试类似的实现。作为额外的安全层,我通过Cython将所有Python源代码编译成。我要做的是取消对导入后从磁盘删除Python模块,同时将其保留在内存中?,python,python-3.x,encryption,Python,Python 3.x,Encryption,我正在尝试对我正在进行的项目的一部分设置加密。现在,我正在尝试类似的实现。作为额外的安全层,我通过Cython将所有Python源代码编译成。我要做的是取消对.pyd模块的加密,导入它,然后立即删除未加密的文件,同时保持模块在内存中可用。我该怎么做? 以下是我用于加密/解密的代码: from hashlib import md5 from Crypto.Cipher import AES from Crypto import Random def derive_key_and_iv(pass
.pyd
模块的加密,导入它,然后立即删除未加密的文件,同时保持模块在内存中可用。我该怎么做?
以下是我用于加密/解密的代码:
from hashlib import md5
from Crypto.Cipher import AES
from Crypto import Random
def derive_key_and_iv(password, salt, key_length, iv_length):
d = d_i = ''.encode()
while len(d) < key_length + iv_length:
d_i = md5(d_i + password.encode() + salt).digest()
d += d_i
return d[:key_length], d[key_length:key_length+iv_length]
def encrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size
salt = Random.new().read(bs - len('Salted__'))
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
out_file.write('Salted__'.encode() + salt)
finished = False
while not finished:
chunk = in_file.read(1024 * bs)
if len(chunk) == 0 or len(chunk) % bs != 0:
padding_length = (bs - len(chunk) % bs) or bs
chunk += (padding_length * chr(padding_length)).encode()
finished = True
out_file.write(cipher.encrypt(chunk))
def decrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size
salt = in_file.read(bs)[len('Salted__'):]
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
next_chunk = b''
finished = False
while not finished:
chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
if len(next_chunk) == 0:
padding_length = chunk[-1]
chunk = chunk[:-padding_length]
finished = True
out_file.write(chunk)
为了测试,我做了以下工作:
>>> import os
>>> origpath = r'C:\test\test_me_pls.pyd'
>>> encpath = r'C:\test\blue.rrr'
>>> decpath = r'C:\test\test_me_pls.pyd'
>>> key = 'hello'
>>> with open(origpath,'rb') as inf, open(encpath,'wb') as outf:
... encrypt(inf,outf,key)
>>> os.remove(origpath)
>>> import test_me_pls
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'test_me_pls'
好的,解密成功了。
现在已导入模块,我想删除未加密的.pyd
文件:
>>> os.remove('test_me_pls.pyd')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [WinError 5] Access is denied: 'test_me_pls.pyd'
操作系统删除('test\u me\u pls.pyd'))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
PermissionError:[WinError 5]访问被拒绝:“test\u me\u pls.pyd”
好的。不是我所希望的。为了打败一匹死马:
>>> test_me_pls.__file__
'.\\test_me_pls.pyd'
>>> os.remove(test_me_pls.__file__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [WinError 5] Access is denied: '.\\test_me_pls.pyd'
>>请测试我的文件__
“.\\test\u me\u pls.pyd”
>>>删除操作系统(请测试我的文件)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
PermissionError:[WinError 5]访问被拒绝:'.\\test\u me\u pls.pyd'
有办法做到这一点吗?
注意:我知道如果有人真的想获取我的代码,我编译并加密它并不重要,因为如果他们知道自己在做什么,他们仍然可以通过使用调试器并在适当的位置设置断点来获取未加密的
.pyd
文件,解压缩.pyd
文件等。在此处插入反向工程技术。我想要的是能够防止随意查看此模块中的代码。我房子前门上的锁很容易被有正确知识和工具的人找到,但这并不意味着我不想费心锁门
第二条注意:如果有什么不同,我使用的是Python 3.3我发现了一个解决方法,它忽略了上面的特定
PermissionError
问题,但解决了解密Python模块,然后在Python中运行它,而不在磁盘上保留任何时间的模块解密副本的问题
作为起点,我决定修改上面的decrypt
函数,以返回字符串,而不是写入文件。然后,我可以将该字符串作为模块导入,并从Python中运行代码——同时从不将解密后的模块保存到磁盘。不幸的是,为了实现这一点,我必须从一个加密的.py
文件开始,而不是像我最初想要的那样,从一个加密的和编译的.pyd
文件开始。(如果有人知道如何将字节
对象作为模块导入,请告诉我!)
不管怎样,下面是我为让它工作所做的具体更改 首先,新的
解密函数:
def decrypt(in_file, password, key_length=32):
bs = AES.block_size
salt = in_file.read(bs)[len('Salted__'):]
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
next_chunk = b''
b = b''
finished = False
while not finished:
chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
if len(next_chunk) == 0:
padding_length = chunk[-1]
chunk = chunk[:-padding_length]
finished = True
b += chunk
return b.decode() # Note: will only work if unencrypted file is text, not binary
为了彻底起见,让我们加密原始文件,删除未加密的文件,然后解密,将源代码返回到字符串,s
:
>>> import os
>>> origpath = r'C:\test\test_me_pls.py'
>>> encpath = r'C:\test\blue.rrr'
>>> key = 'hello'
>>> with open(origpath,'rb') as inf, open(encpath,'wb') as outf:
... encrypt(inf,outf,key)
>>> os.remove(origpath)
>>> import test_me_pls
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'test_me_pls'
>>> with open(encpath,'rb') as inf:
... s = decrypt(inf,key)
然后,为了更好地测量,我们可以将模块添加到sys
,使其忽略后续的导入尝试:
>>> sys.modules['test_me_pls'] = test_me_pls
然后,因为我们的最初目标是使源代码更难阅读,所以让我们去掉包含源代码的字符串:
>>> del s
最后,作为一个健全性检查,确保在源字符串消失后模块仍然工作:
>>> test_me_pls.square(3)
9
如果任何人有任何替代解决方案(特别是如何修复WindowsPermissionError
问题或从bytes
对象而不是文件导入二进制.pyd
),请告诉我 我找到了一种解决方法,它忽略了上面特定的PermissionError
问题,但解决了对Python模块进行解密,然后在Python中运行它,而不在磁盘上保留任何时间的模块解密副本的问题
作为起点,我决定修改上面的decrypt
函数,以返回字符串,而不是写入文件。然后,我可以将该字符串作为模块导入,并从Python中运行代码——同时从不将解密后的模块保存到磁盘。不幸的是,为了实现这一点,我必须从一个加密的.py
文件开始,而不是像我最初想要的那样,从一个加密的和编译的.pyd
文件开始。(如果有人知道如何将字节
对象作为模块导入,请告诉我!)
不管怎样,下面是我为让它工作所做的具体更改
首先,新的解密函数:
def decrypt(in_file, password, key_length=32):
bs = AES.block_size
salt = in_file.read(bs)[len('Salted__'):]
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
next_chunk = b''
b = b''
finished = False
while not finished:
chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
if len(next_chunk) == 0:
padding_length = chunk[-1]
chunk = chunk[:-padding_length]
finished = True
b += chunk
return b.decode() # Note: will only work if unencrypted file is text, not binary
为了彻底起见,让我们加密原始文件,删除未加密的文件,然后解密,将源代码返回到字符串,s
:
>>> import os
>>> origpath = r'C:\test\test_me_pls.py'
>>> encpath = r'C:\test\blue.rrr'
>>> key = 'hello'
>>> with open(origpath,'rb') as inf, open(encpath,'wb') as outf:
... encrypt(inf,outf,key)
>>> os.remove(origpath)
>>> import test_me_pls
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'test_me_pls'
>>> with open(encpath,'rb') as inf:
... s = decrypt(inf,key)
然后,为了更好地测量,我们可以将模块添加到sys
,使其忽略后续的导入尝试:
>>> sys.modules['test_me_pls'] = test_me_pls
然后,因为我们的最初目标是使源代码更难阅读,所以让我们去掉包含源代码的字符串:
>>> del s
最后,作为一个健全性检查,确保在源字符串消失后模块仍然工作:
>>> test_me_pls.square(3)
9
如果任何人有任何替代解决方案(特别是如何修复WindowsPermissionError
问题或从bytes
对象而不是文件导入二进制.pyd
),请告诉我 “防止随意查看此模块中的代码的东西”-您的意思是分发.pyd
?@jornsharpe是的。我正在这么做,但我希望有人能通过另一层烦恼来获得代码。一种有趣的方法。一个猜测,但我认为如果你达到了操作系统的限制会发生什么:在Windows上,如果某个进程打开了一个文件,你就不能删除它。我很确定这在Linux上可以正常工作。你能做的是一个)数字