我想在Redshift中创建以下加密和解密UDF。
库:
create library pyaes
language plpythonu
from 's3://aws_python/library/pyaes/pyaes.zip'
credentials 'aws-role'
region as 'aws-region';
加密:
CREATE OR REPLACE FUNCTION test.aes_encrypt(input varchar(max))
RETURNS varchar(max) AS
' if input is None:
return None
import pyaes
key = ''abcdefghijklopoo''
aes = pyaes.AESModeOfOperationCTR(key)
encrypted_msg = aes.encrypt(input)
return encrypted_msg
'
LANGUAGE plpythonu STABLE;
还尝试了以下选项:
encrypted_msg = aes.encrypt(input.encode("utf8"))
key = key.encode('utf-8')
解密:
CREATE OR REPLACE FUNCTION test.aes_decrypt(encrypted_msg varchar(max))
RETURNS varchar(max) AS
'
if encrypted_msg is None or len(str(encrypted_msg)) == 0:
return None
import pyaes
key = ''abcdefghijklopoo''
aes = pyaes.AESModeOfOperationCTR (key)
decrypted_msg = aes.decrypt(encrypted_msg).decode("utf8")
return decrypted_msg
'
LANGUAGE plpythonu STABLE;
选择aes_encrypt('Testing'); 选择aes_decrypt('');
但是它抛出以下错误:
错误:无效的操作:字符串包含无效或不受支持的UTF8代码点。错误的UTF8十六进制序列:d5 fc(错误4);
请告知。预先感谢。
答案 0 :(得分:2)
我在一个可以查看输出的笔记本上进行了此操作。基本上,在发生AES函数时会发生错误,您看不到它的输出,并且它将错误类型传递回Redshift,因为aes作为字节返回。
请注意:这是为了对数据列进行加密混淆,而不是服务器端加密。如果安全性至关重要,请对整个数据库进行加密。如果您打算用它来保护您的客户数据,请不要,请加密盐并哈希所有内容等。这是您的免责声明。
这需要转换为redshift可以处理的东西,例如十六进制,所以使用 'binascii.hexlify(cipher_txt)'以可打印的方式取回值。
CREATE OR REPLACE FUNCTION aes_encrypt(input VARCHAR(20000))
RETURNS VARCHAR STABLE AS $$
import pyaes
import binascii
if input is None:
return None
key = 'abcdefghijklnosp'
aes=pyaes.AESModeOfOperationCTR(key)
cipher_txt=aes.encrypt(input)
cipher_txt2=binascii.hexlify(cipher_txt)
return str(cipher_txt2.decode('utf-8'))
$$ LANGUAGE plpythonu ;
请注意,返回时的解码是多余的,并且密文分为几行进行说明。我相信您可以将它们放回一行。喜欢
cipher_txt = binascii.hexlify(aes.encrypt(input))
要取消加密:
CREATE OR REPLACE FUNCTION aes_decrypt(encrypted_msg varchar(max))
RETURNS VARCHAR STABLE AS $$
import pyaes
import binascii
if encrypted_msg is None or len(str(encrypted_msg)) == 0:
return None
key = 'abcdefghijklnosp'
aes = pyaes.AESModeOfOperationCTR(key)
encrypted_msg2=binascii.unhexlify(encrypted_msg)
decrypted_msg2 = aes.decrypt(encrypted_msg2)
return str(decrypted_msg2.decode('utf-8'))
$$ LANGUAGE plpythonu ;
另外-旁注-除非由于其他原因(联合或类似的原因)而无需指定返回varchar的长度-因为将所有内容都设为max会浪费空间。