解密Fernet CSV,编码问题?Pandas

yqlxgs2m  于 2023-08-01  发布在  其他
关注(0)|答案(2)|浏览(90)

我无法解密CSV文件。我运行正常的加密过程,然后导出到csv。然后我重新加载并尝试解密。
如果我屏蔽了csv导入行,脚本将按预期正确解密。
我收到的错误说:

InvalidToken: occurred at index Name

字符串
我尝试了各种编码/解码的迭代,但都无济于事。

# import data
data = {'name': ["Joe", "Joe", "Joe","Jane","Jane"],
        'job': ["Analyst","Manager","Director","Analyst","Manager"],
        '#': [1,2,3,4,5],
        'yrs_serv': [1.1, 1.2, 1.3, 1.4, 1.5]}
df = pd.DataFrame(data, columns=['name', 'job', '#', 'yrs_serv'])

# generate key
encrypt_key = Fernet.generate_key()

f = Fernet(encrypt_key)
df = df_e.apply(lambda x: x.astype(str)) # preprocess
token = df.applymap(lambda x: f.encrypt(x.encode('utf-8')))

# the file goes out to a vendor, and they join some data and send back
# (I'll delete the new data concatenate it back into the df once the data is decrypted)
token.to_csv('encrypted_file.csv', index=False)

token = pd.read_csv('encrypted_file.csv') 

token = token.applymap(lambda x: x.encode('utf-8')) # seems the file import wasn't in utf-8

df_decrp = token.applymap(lambda x: f.decrypt(x))

ctzwtxfj

ctzwtxfj1#

对于示例(更正):

# import data
data = {'name': ["Joe", "Joe", "Joe","Jane","Jane"],
        'job': ["Analyst","Manager","Director","Analyst","Manager"],
        '#': [1,2,3,4,5],
        'yrs_serv': [1.1, 1.2, 1.3, 1.4, 1.5]}
df = pd.DataFrame(data, columns=['name', 'job', '#', 'yrs_serv'])

# generate key
encrypt_key = Fernet.generate_key()

f = Fernet(encrypt_key)
df_e = df.apply(lambda x: x.astype(str)) # preprocess
token = df_e.applymap(lambda x: f.encrypt(x.encode('utf-8')))
token.to_csv('encrypted_file.csv', index=False)

字符串
解码任务是:

token2 = pd.read_csv('encrypted_file.csv') 
token3 = token2.applymap(lambda x: bytes(x[2:-1],'utf-8'))
token4 = token3.applymap(lambda x: f.decrypt(x))
df_decrp = token4.applymap(lambda x: x.decode('utf-8'))
df_decrp


结果是:

name     job        #   yrs_serv
0   Joe     Analyst     1    1.1
1   Joe     Manager     2    1.2
2   Joe     Director    3    1.3
3   Jane    Analyst     4    1.4
4   Jane    Manager     5    1.5


其中每个元素都是一个字符串。在你可以将字符串转换为数字之后
解释:让我们取column=#和row=0中的元素
token['#'][0] = b'gAAAAAB......'(100字节)
当字节写入文件csv token2['#'][0] ="b'gAAAAAB......'"时(字符串= 103个字符)
如果您用途:

token3 = token2.applymap(lambda x: x.encode('utf-8'))


token3['#'][0] =b"b'gAAAAAB......'"(103字节!!)
为了解密数据,我必须有一个等于token的DataFrame,但是token 3,在本例中,不同于token!你不能用它
所以在将字符串转换为字节之前,你必须消除前两个字符“b和最后一个”

token3 = token2.applymap(lambda x: x[2:-1])


token3['#'][0] =b'gAAAAAB......'(100字节)

enxuqcxy

enxuqcxy2#

Andrea Mannari给出了一个很好的答案,基本上解决了我的问题,但我想更好地解释为什么字节串切片是必要的,所以经过一些调查,这就是我的发现。
DataFrame中的每个元素都存储为字节字符串,如果你打印DataFrame,你会清楚地看到元素是b '编码文本',表示它们是字节字符串,所以下面的代码应该给予解密的字节字符串,但它没有。

f.decrypt(token2['name'][0])
"b'encrypted text'"

字符串
问题是,当你用这种方式使用pandas元素时,pandas显然会对它应用__str()__函数,从而将字节字符串转换成一个封装在普通字符串中的字节字符串。

token2['name'][0].__str__()  
"b'encrypted text'"


这个问题的解决方案是通过使用eval()函数强制pandas将字节字符串作为字节字符串计算,因此下面的代码将生成一个字节字符串,我们可以使用它来解码(从字节字符串转换为普通字符串)和解密(加密和解密字节字符串)。

eval(token2['name'][0])
b'encrypted text'


我还为列标题添加了加密。下面是我对Andrea代码的版本。

import pandas as pd
from cryptography.fernet import Fernet 

data = {'name': ["Joe", "Joe", "Joe","Jane","Jane"],
    'job': ["Analyst","Manager","Director","Analyst","Manager"],
    '#': [1,2,3,4,5],
    'yrs_serv': [1.1, 1.2, 1.3, 1.4, 1.5]}

df = pd.DataFrame(data, columns=['name', 'job', '#', 'yrs_serv'])
print(f'orig df \n{df}\n')

# generate key
# encrypt_key = Fernet.generate_key()
encrypt_key = b'gB07ncUSR2oFkeUGD8_gM_CcBQvfWwslrXg3QZOAqII='

# Use key to encrypt data
f = Fernet(encrypt_key)
df_e = df.apply(lambda x: x.astype(str)) # preprocess
token = df_e.applymap(lambda x: f.encrypt(x.encode('utf-8')))

# Encrypt column headings
token.columns = [f.encrypt(bytes(x,'utf-8')) for x in df_e.columns]

# Save to CSV file
token.to_csv('encrypted_file.csv', index=False)
print(f'encrypted df \n{token}\n')

#Read and decoding CSV:
token2 = pd.read_csv('encrypted_file.csv')

# Decrypt column headings first
token2.columns = [f.decrypt(eval(x).decode('utf-8')).decode('utf-8') for x in token2.columns]

# Decrypt the CSV data
df_decrp = token2.applymap(lambda x: f.decrypt(eval(x).decode('utf-8')).decode('utf-8'))
print(f'decrypted df \n{df_decrp}\n', )


解密CSV数据涉及以下步骤:
将元素计算为字节字符串

eval(x)


将字节串解码为普通字符串

eval(x).decode('utf-8')


解密正常字符串,生成字节字符串

f.decrypt(eval(x).decode('utf-8'))


将解密后的字节串解码为正常字符串

f.decrypt(eval(x).decode('utf-8')).decode('utf-8')


有关字节串Convert bytes to a string in python 3的解码和编码,请参阅此链接

相关问题