gpt4 book ai didi

python - 将文件解密为流并将流读入 p​​andas(hdf 或 stata)

转载 作者:太空宇宙 更新时间:2023-11-03 11:25:25 25 4
gpt4 key购买 nike

我正在尝试做的事情的概述。我有需要读入 Pandas 的文件的加密版本。出于几个原因,解密成流而不是文件要好得多,所以这是我下面的兴趣,尽管我也尝试解密成文件只是作为中间步骤(但这也不起作用)。

我能够使它适用于 csv,但不适用于 hdf 或 stata(我接受适用于 hdf 或 stata 的答案,尽管两者的答案可能相同,这就是为什么我正在合并一个问题)。

加密/解密文件的代码取自另一个stackoverflow问题(目前我找不到)。

import pandas as pd
import io
from Crypto import Random
from Crypto.Cipher import AES

def pad(s):
return s + b"\0" * (AES.block_size - len(s) % AES.block_size)

def encrypt(message, key, key_size=256):
message = pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(message)

def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return plaintext.rstrip(b"\0")

def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(plaintext, key)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)

def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
with open(file_name[:-4], 'wb') as fo:
fo.write(dec)

这是我尝试扩展代码以解密到流而不是文件。

def decrypt_stream(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
cipherbyte = io.BytesIO()
cipherbyte.write(dec)
cipherbyte.seek(0)
return cipherbyte

最后,这里是带有示例数据的示例程序,试图使这项工作成功:

key = 'this is an example key'[:16]
df = pd.DataFrame({ 'x':[1,2], 'y':[3,4] })

df.to_csv('test.csv',index=False)
df.to_hdf('test.h5','test',mode='w')
df.to_stata('test.dta')

encrypt_file('test.csv',key)
encrypt_file('test.h5',key)
encrypt_file('test.dta',key)

decrypt_file('test.csv.enc',key)
decrypt_file('test.h5.enc',key)
decrypt_file('test.dta.enc',key)

# csv works here but hdf and stata don't
# I'm less interested in this part but include it for completeness
df_from_file = pd.read_csv('test.csv')
df_from_file = pd.read_hdf('test.h5','test')
df_from_file = pd.read_stata('test.dta')

# csv works here but hdf and stata don't
# the hdf and stata lines below are what I really need to get working
df_from_stream = pd.read_csv( decrypt_stream('test.csv.enc',key) )
df_from_stream = pd.read_hdf( decrypt_stream('test.h5.enc',key), 'test' )
df_from_stream = pd.read_stata( decrypt_stream('test.dta.enc',key) )

不幸的是,我不认为我可以再压缩这段代码并仍然有一个完整的例子。

同样,我希望所有 4 条非工作行都能正常工作(hdf 和 stata 的文件和流),但我很高兴接受一个适用于单独的 hdf 流或单独的 stata 流的答案.

此外,我对其他加密替代方案持开放态度,我只是使用了一些我在 SO 上找到的现有的基于 pycrypto 的代码。我的工作明确需要 256 位 AES,但除此之外我是开放的,因此该解决方案不需要专门基于 pycrypto 库或上面的特定代码示例。

关于我的设置的信息:

python: 3.4.3
pandas: 0.17.0 (anaconda 2.3.0 distribution)
mac os: 10.11.3

最佳答案

最大的问题是 padding/unpadding 方法。它假定空字符不能成为实际内容的一部分。由于 stata/hdf 文件是二进制文件,因此使用我们使用的额外字节数(编码为字符)进行填充更安全。这个数字将在取消填充期间使用。

同样目前,read_hdf 不支持从对象等文件中读取,即使 API 文档声称支持。如果我们将自己限制为 stata 格式,则以下代码将执行您需要的操作:

import pandas as pd
import io
from Crypto import Random
from Crypto.Cipher import AES

def pad(s):
n = AES.block_size - len(s) % AES.block_size
return s + n * chr(n)

def unpad(s):
return s[:-ord(s[-1])]

def encrypt(message, key, key_size=256):
message = pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(message)

def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return unpad(plaintext)

def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(plaintext, key)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)

def decrypt_stream(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
cipherbyte = io.BytesIO()
cipherbyte.write(dec)
cipherbyte.seek(0)
return cipherbyte

key = 'this is an example key'[:16]

df = pd.DataFrame({
'x': [1,2],
'y': [3,4]
})

df.to_stata('test.dta')

encrypt_file('test.dta', key)

print pd.read_stata(decrypt_stream('test.dta.enc', key))

输出:

   index  x  y
0 0 1 3
1 1 2 4

在 python 3 中,您可以使用以下 padunpad 版本:

def pad(s):
n = AES.block_size - len(s) % AES.block_size
return s + bytearray([n] * n)

def unpad(s):
return s[:-s[-1]]

关于python - 将文件解密为流并将流读入 p​​andas(hdf 或 stata),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34978703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com