Python AES编码/解码字符串并存储在MySQL中
我正在做一个使用Pyramid1.3(Python2.7)并在MySQL中存储数据的项目。我有一个表的电子邮件地址,我想加密他们的存储。我试图在应用程序中加密它们,然后将它们解密以供查看。我不打算完全安全,但主要目的是在数据库本身受损的情况下,对数据进行足够的模糊处理 我将PyCrypto与AES结合使用,并一直在尝试关注这里的一些帖子和我找到的一些web教程。到目前为止,我发现的最接近的方法是,而且似乎有效,至少是对它进行加密。我遵循这一点,并在数据库中存储类似于Python AES编码/解码字符串并存储在MySQL中,python,mysql,encryption,pyramid,pycrypto,Python,Mysql,Encryption,Pyramid,Pycrypto,我正在做一个使用Pyramid1.3(Python2.7)并在MySQL中存储数据的项目。我有一个表的电子邮件地址,我想加密他们的存储。我试图在应用程序中加密它们,然后将它们解密以供查看。我不打算完全安全,但主要目的是在数据库本身受损的情况下,对数据进行足够的模糊处理 我将PyCrypto与AES结合使用,并一直在尝试关注这里的一些帖子和我找到的一些web教程。到目前为止,我发现的最接近的方法是,而且似乎有效,至少是对它进行加密。我遵循这一点,并在数据库中存储类似于“7hBAQrWhJRnL9Y
“7hBAQrWhJRnL9YdBGJfRErGFwGi3aC6noGzYTrGwAoQ=“
”的内容。但decrypt函数始终出现以下错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa1 in position 1: ordinal not in range(128)
我遇到了一些关于Python的unicode演示,这在某种程度上帮助我理解了它,但我仍然不断遇到同样的错误
有关于如何编码、存储在数据库中、从数据库中取出以及解码源数据字符串的简单教程吗
我需要数据库列的特定排序规则吗?字段是否需要为特定类型?到目前为止,我一直在使用默认排序规则并将其设置为VARCHAR,假设我正在存储一个字符串。听起来好像我在某些地方遇到了一些编码问题,比如不兼容的类型之类的问题,但我的脑袋一直在转,我需要在哪里修改一些东西
我能提供更好的指示或其他什么吗?我可以显示我的代码,但它基本上是上面链接的副本。。。我只是想在对其进行太多修改之前,让概念验证生效
编辑:
一些样本源。。。
在MySQL中,表是
id(int)
客户id(int)
emailaddress varchar(100)utf8mb4_general_ci(我一直在玩排序规则,我不知道它应该是什么!)
Python:
from base64 import b64encode, b64decode, urlsafe_b64decode, urlsafe_b64encode
BLOCK_SIZE = 32
INTERRUPT = u'\u0001'
PAD = u'\u0000'
def AddPadding(data, interrupt, pad, block_size):
new_data = ''.join([data, interrupt])
new_data_len = len(new_data)
remaining_len = block_size - new_data_len
to_pad_len = remaining_len % block_size
pad_string = pad * to_pad_len
return ''.join([new_data, pad_string])
def StripPadding(data, interrupt, pad):
return data.rstrip(pad).rstrip(interrupt)#data.rsplit(interrupt,1)[0]#rstrip(pad).rstrip(interrupt)
SECRET_KEY = u'a1b2c3d4e5f6g7h8a1b2c3d4e5f6g7h8'
IV = u'12345678abcdefgh'
cipher_for_encryption = AES.new(SECRET_KEY, AES.MODE_CBC, IV)
cipher_for_decryption = AES.new(SECRET_KEY, AES.MODE_CBC, IV)
def EncryptWithAES(encrypt_cipher, plaintext_data):
plaintext_padded = AddPadding(plaintext_data, INTERRUPT, PAD, BLOCK_SIZE)
encrypted = encrypt_cipher.encrypt(plaintext_padded)
return urlsafe_b64encode(encrypted)
def DecryptWithAES(decrypt_cipher, encrypted_data):
decoded_encrypted_data = urlsafe_b64decode(encrypted_data)
decrypted_data = decrypt_cipher.decrypt(decoded_encrypted_data)
return StripPadding(decrypted_data, INTERRUPT, PAD)
#encrypts it
posted_singleaddress = EncryptWithAES(cipher_for_encryption, posted_singleaddress)
#"me@mail.com" inserts "Ktpr49Uzn99HZXbmqEzGKlWo9wk-XBMXGZl_iyna-8c=" into the database
clientemails是上表中的电子邮件列表。我在取消注释时出错:
#if clientemails:
# decrypted = DecryptWithAES(cipher_for_decryption, clientemails[0].emailaddress)
我只是试着解码第一个项目,只是为了让它工作,但这似乎是让它适合现在的部分…PyCrypto的一般规则是,加密密钥、IVs、明文、填充和密文应该始终定义为二进制字符串,而不是文本。对它们使用Unicode本身就是问题的根源 另一个问题是您要以十六进制编码形式传递给AES.newkey和IV,因此前者是256位,而后者是128位。这似乎仍然有效,但我猜您的意图是使用AES128,它有一个128位的密钥。因此,您需要将其转换为二进制,例如通过
unexlify
:两个字符串b'34'将映射到单个字节'\x34'。静脉注射需要两倍长
因此,在您的代码中最好有:
from binascii import unhexlify
INTERRUPT = b'\x01'
PAD = b'\x00'
SECRET_KEY = unhexlify('a1b2c3d4e5f6g7h8a1b2c3d4e5f6g7h8')
IV = unhexlify('12345678abcdefgh'*2)
如果您需要对文本进行加密,您可以先对其进行编码(如UTF-8),然后将其传递给函数EncryptWithAES()
。另请参见以下示例:
加密步骤的结果(即密文)也是一个二进制字符串。为了将其直接存储在MySQL数据库中,您必须使用
BINARY
或VARBINARY
类型列。您可以发布代码中有问题的部分吗?通过添加编辑…您是否验证了AddPadding
和stripppadding
是否按预期工作?第二个定义是“fits”,它会引发异常,还是只会给你错误的数据?如果它抛出异常,异常是什么,我们可以看到回溯吗?我一直得到的错误是“UnicodeDecodeError:'ascii'编解码器无法解码位置1中的字节0xa1:序号不在范围(128)”内。这听起来似乎是比较常见的,是由于ascii和unicode之间的转换或其他原因。回溯看起来像:文件“/home/peter/dev/env/myproj/myproj/views.py”,第320行,在view\u clientemails decrypted=DecryptWithAES(用于解密的密码,email.emailaddress)文件“/home/peter/dev/env/myproj/myproj/views.py”,第114行,DecryptWithAES返回StripPadding(解密的_数据,中断,PAD)文件“/home/peter/dev/env/myproj/myproj/views.py”,第79行,在StripPadding返回数据.rstrip(PAD).rstrip(中断)中
from Crypto.Cipher import AES
from Crypto import Random
key = b'Sixteen byte key'
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = iv + cipher.encrypt(b'Attack at dawn')