Redshift Python 加密/解密 UDF 错误 - 字符串包含无效或不受支持的 UTF8 代码点

Posted

技术标签:

【中文标题】Redshift Python 加密/解密 UDF 错误 - 字符串包含无效或不受支持的 UTF8 代码点【英文标题】:Redshift Python encrypt/decrypt UDF Error - String contains invalid or unsupported UTF8 codepoints 【发布时间】:2018-08-02 21:33:12 【问题描述】:

我想在 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('测试'); 选择 aes_decrypt('');

但它抛出以下错误:

错误:无效操作:字符串包含无效或不受支持的 UTF8 代码点。错误的 UTF8 十六进制序列:d5 fc(错误 4);

请指教。提前致谢。

【问题讨论】:

你为什么首先认为输入是 UTF-8? 嗨,当我创建函数并在 select 语句中使用它时,它会抛出错误:无效操作:字符串包含无效或不受支持的 UTF8 代码点。错误的 UTF8 十六进制序列:d5 fc(错误 4);因此,我尝试使用 utf-8 编码,但仍然抛出相同的错误。 请对此提出建议。不知道我在这段代码中哪里做错了。 @IgnacioVazquez-Abrams 你能建议一下吗? ***.com/questions/51735127/… 【参考方案1】:

我在一个可以查看输出的笔记本中完成了这项工作。基本上,当 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 的长度,除非你需要出于其他原因(联合或类似的) - 因为使一切都最大化是浪费空间。

【讨论】:

以上是关于Redshift Python 加密/解密 UDF 错误 - 字符串包含无效或不受支持的 UTF8 代码点的主要内容,如果未能解决你的问题,请参考以下文章

使用Java继承UDF类或GenericUDF类给Hive3.1.2编写UDF实现编码解码加密解密并运行在USDP大数据集群

使用Java继承UDF类或GenericUDF类给Hive3.1.2编写UDF实现编码解码加密解密并运行在USDP大数据集群

在 Redshift 中创建 python UDF 时出错

您可以从 Redshift 中的 python UDF 返回多个值吗?

使用自定义 Python 库 ua-parser 的 Amazon Redshift UDF

Redshift 中的 Python UDF 函数始终返回 NULL 值