我试图通过此python代码使用AES加密数据库中的一些敏感数据
from Crypto.Cipher import AES
import base64
import pymysql
import os
import hashlib
def encryption(self, tableName):
# opening db connection
db_connection = self.getMySqlConnection()
cursor = db_connection.cursor()
print("\tTwo Way Encryption")
# hashing
cursor.execute("SELECT toMask FROM " + tableName + ";")
row = cursor.fetchall()
for item in row:
string = str(item[0])
padded = string.rjust(80)
secret_key = self.key
cipher = AES.new(secret_key, AES.MODE_ECB)
encoded = base64.b64encode(cipher.encrypt(padded))
encoded = encoded.decode('utf-8')
stmt = "update " + tableName + " set toMask = '" + encoded + "' where toMask =\"" + string + "\";"
cursor.execute(stmt)
db_connection.commit()
# closing db connection
db_connection.close()
print("\tDone")
但我的数据包含一些像这样的特殊字符
A
所以我收到了这个错误:
ValueError: Input strings must be a multiple of 16 in length
我该如何解决这个问题?其他输入字符串不会产生任何问题。
或者我是否需要将其转换为任何其他编码?
答案 0 :(得分:0)
Crypto.cipher
documentation不完整,未指定填充的处理方式。猜测是它希望调用者进行填充。 (如果您编写开源代码,请提供预期功能和完整文档。在这种情况下,应支持PKCS#7填充,并应指定输入类型(二进制,字符串,十六进制,Base64)。)
似乎还需要字节:cipher.encrypt(b'Attack at dawn')
,注意 b 。
因为必须填充并提供二进制文件,所以必须首先转换为二进制文件然后填充,以便cipher
的输入是块大小的倍数(AES为16字节)。
空填充是不好的是有数据的人有一个0x00字节作为最后一个字节,一般填充是PKCS#7。
请您编写开源代码,提供预期的功能和完整的文档。在这种情况下,应支持PKCS#7填充,并应指定输入类型(二进制,字符串,十六进制,Base64等)。
答案 1 :(得分:0)
我得到了我的问题的答案。我是为了任何可能面临这个问题的其他同事的利益而分享这个。
实际上,这些数据的编码存在差异。所以我所做的是,在填充之前将字符串编码为utf-8。然后用16的倍数填充它,然后加密数据。之后我解码并将其更新到数据库。这样,问题就解决了。
所以代码看起来像这样:
from Crypto.Cipher import AES
import base64
import pymysql
import os
import hashlib
def encryption(self, tableName, paddingLength):
# opening db connection
db_connection = self.getMySqlConnection()
cursor = db_connection.cursor()
print("\tTwo Way Encryption")
# hashing
cursor.execute("SELECT toMask FROM " + tableName + ";")
row = cursor.fetchall()
for item in row:
string = str(item[0])
#convert to string
strng = str(string)
#encode to utf-8
string = string.encode('utf-8')
#pad with length 80
padded = string.rjust(80)
secret_key = self.key
cipher = AES.new(secret_key, AES.MODE_ECB)
encoded = base64.b64encode(cipher.encrypt(padded))
#decode utf-8
encoded = encoded.decode('utf-8')
encoded = str(encoded)
# deselect strict mode
cursor.execute("SET @@global.sql_mode= 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';")
stmt = "update " + tableName + " set toMask = \"" + encoded + "\" where toMask =\"" + strng + "\";"
# print(stmt)
cursor.execute(stmt)
db_connection.commit()
# closing db connection
db_connection.close()
print("\tDone")
所以只需将其编码为utf-8即可解决问题。