云原生数据仓库 AnalyticDB PostgreSQL 版内置加密解密模块pgcryoto并集成国密SM4加密算法,允许数据库用户以加密形式存储数据的某些列,为敏感数据增加了一层额外的保护。无密钥时,任何用户都无法读取以加密形式存储在数据库中的数据。

注意事项

pgcrypto插件在数据库服务器内部运行,所有数据和密码都以明文形式在数据库和客户端应用程序之间传输。为了获得最佳安全性,建议在客户端和云原生数据仓库 AnalyticDB PostgreSQL 版之间使用SSL连接。

安装pgcrypto插件

使用pgcryoto插件之前,请您在云原生数据仓库 AnalyticDB PostgreSQL 版实例插件管理中安装pgcrypto插件。具体操作,请参见安装、升级与卸载插件

通用哈希函数

digest()函数可以根据不同的算法生成数据的二进制哈希值。

语法

digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea
  • data:需要计算二进制哈希值的原始数据。

  • type:加密算法。包括MD5、SHA1、SHA224、SHA256、SHA384和SHA512。

示例

使用digest()函数对字符串ADBPG进行sha256加密存储,示例如下。

SELECT digest('ADBPG','sha256');

返回结果如下。

                               digest
--------------------------------------------------------------------
 \x2d0525fa98e83619424dc1303ba107c59aabb389bbe94ceef885c742088560bc
(1 row)

密码哈希函数

crypt()gen_salt()函数专用于哈希密码。crypt()执行哈希用于加密数据,gen_salt()用于生成加盐哈希。

crypt()函数中的算法和普通的MD5或者SHA1哈希算法存在以下不同之处:

  • crypt()函数中算法很慢。密码通常长度较小,crypt()只能用比较复杂的加密算法来增加破解难度。

  • crypt()函数使用一个随机值(Salt,即盐值),使得具有相同口令的用户将得到不同的密文口令。这也是针对破解算法提供一种额外的安全保护。

  • crypt()函数的结果中包括了算法类型,因此可以针对不同用户使用不同的算法对密码进行加密。

  • crypt()函数的一些算法具有自适应性,意味着当计算机性能变得更快时,可以调整该算法使其变得更慢,而不会产生与已有密码的不兼容性。

crypt()函数支持的算法

算法

密码最大长度

是否自适应

Salt 位数

输出长度

描述

BF

72

128

60

基于Blowfish的变体2a算法。

MD5

unlimited

48

34

基于MD5的加密算法。

XDES

8

24

20

扩展DES。

DES

8

12

13

原生UNIX加密。

crypt()语法

crypt(password text, salt text) returns text 

crypt()函数返回password字符串的哈希值,salt参数由gen_salt()函数生成。由于gen_salt()函数每次都会生成不同的salt,因此对于相同的password字符串,crypt()函数每次也会返回不同的结果。校验密码时可以将之前生成的哈希结果作为salt。

crypt()示例

  • 示例一:通过crypt()函数设置一个新密码。

    UPDATE ... SET pswhash = crypt('my_password', gen_salt('md5')); 
  • 示例二:通过比较存储的密码哈希值验证输入的密码的正确性。

    SELECT (pswhash = crypt('entered password', pswhash)) AS pswmatch FROM ... ; 

    如果输入的口令正确,会返回true。

gen_salt()语法

gen_salt(type text [, iter_count integer ]) returns text 

gen_salt()函数用来产生随机的参数输入给crypt,此函数每次都会生成一个随机的盐值(salt)字符串,该字符串同时决定了crypt()函数使用的算法。

type:用于指定一个生成字符串的哈希算法,取值包括DES、XDES、MD5及BF。

iter_count:对于XDES和BF算法,iter_count指定迭代次数,数字越大加密时间越长,被破解需要的时间也越长。

gen_salt()示例

SELECT gen_salt('des'), gen_salt('xdes'), gen_salt('md5'), gen_salt('bf');

返回结果如下。

 gen_salt | gen_salt  |  gen_salt   |           gen_salt            
----------+-----------+-------------+-------------------------------
 qh       | _J9..uEUi | $1$SNgqyKAi | $2a$06$B/Etc3J8zYBV49LrDU97MO
(1 row)

PGP加密函数

云原生数据仓库 AnalyticDB PostgreSQL 版实现了OpenPGP(RFC 4880)标准,支持对称加密和非对称加密。

pgp_sym_encrypt()

pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea 
pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea 

pgp_sym_encrypt()用于对称密钥加密。

  • data:需要加密的数据。

  • psw:PGP对称密钥。

  • options:用于设置选项。

pgp_sym_decrypt()

pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text 
pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea 

pgp_sym_decrypt()用于解密PGP对称密钥加密后的消息。

  • msg:需要解密的消息。

  • psw:PGP对称密钥。

  • options:用于设置选项。

为了避免输出无效的字符,不允许使用pgp_sym_decrypt函数对Bytea数据进行解密,可以使用 pgp_sym_decrypt_bytea对原始文本数据进行解密。

pgp_pub_encrypt()

pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea 
pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea 

pgp_pub_encrypt()用于公钥密钥加密。

  • data:需要加密的数据。

  • key:PGP公钥,如果传入一个私钥将会返回错误。

  • options:用于设置选项。

pgp_pub_decrypt()

pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text 
pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea 

pgp_pub_decrypt()用于解密一个公共密钥加密的消息。

  • msg:需要解密的消息。

  • key:必须是用于加密的公钥的私钥。如果私钥是用口令保护的,必须在psw中给出该口令。如果没有口令,但想要指定选项,需要给出一个空口令。

为了避免输出无效的字符,不允许使用pgp_pub_decrypt函数对Bytea数据进行解密,可以使用pgp_pub_decrypt_bytea对原始文本数据进行解密。key为公共密钥对应的私钥,如果私钥使用了密码保护功能,必须在psw参数中指定密码;如果没有使用密码保护,想要指定options参数时必须指定一个空的psw

随机数据函数

gen_random_bytes()

gen_random_bytes(count integer) returns bytea 

gen_random_bytes()函数用于生成具有强加密性的随机字节。

count:返回的字节数,取值为1~1024。

示例:

SELECT gen_random_bytes(16);

返回结果如下。

          gen_random_bytes          
------------------------------------
 \x1f1eddc11153afdde0f9e1229f8f4caf
(1 row)

gen_random_uuid()

gen_random_uuid()函数用于返回一个Version 4的随机UUID。

示例:

SELECT gen_random_uuid();

返回结果如下。

gen_random_uuid 
--------------------------------------
2bd664a2-b760-4859-8af6-8d09ccc5b830

国密SM4加密算法

根据信息安全的相关要求,敏感信息通常需要在数据库中进行加密存储,例如登录密码、信用卡号、身份证号等。pgcrypto插件提供了多种加密算法,总体上分为单向加密和双向加密:

  • 单向加密:属于不可逆加密,无法根据密文解密出明文,适用于数据的验证,例如登录密码验证。

  • 双向加密:属于可逆加密,根据密文和密钥可解密出明文,适用于数据的安全传输,例如电子支付、数字签名等。

云原生数据仓库 AnalyticDB PostgreSQL 版还支持国密算法SM4。SM4属于双向加密,您需要提供密钥,在数据库服务端进行加密。

重要
  • SM4算法目前只支持Text和Varchar数据类型,应用开发人员需要在业务侧将待加密的数据转成字符串(String)后,再进行加密。

  • 仅支持V6.3.8.9及以上版本,安装或升级插件需要如何查看实例内核版本,请参见查看内核小版本

安装

使用国密算法SM4之前,您需要在云原生数据仓库 AnalyticDB PostgreSQL 版实例插件管理中安装pgcrypto插件。具体操作,请参见安装、升级与卸载插件

加密

使用SM4函数加密关键字段语法如下。

-- 加密text格式数据
sm4_encrypt_text(<data text>, <password text>)

-- 加密varchar格式数据
sm4_encrypt_varchar(<data varchar>, <password text>)

参数说明如下。

参数

说明

data text

需要加密的Text格式的数据。

data varchar

需要加密的Varchar格式的数据。

password text

加密密钥,为Text格式。

  • 示例一:对文本字段who am i进行加密,密钥为key,示例如下。

    SELECT sm4_encrypt_text('who am i','key');

    加密后的值为Bytea类型,返回信息如下。

              sm4_encrypt_text
    ------------------------------------
     \x308b71cc7fa0de7d720b2c394a3a83c2
    (1 row)
  • 示例二:使用SM4加密函数将明文数据转成密文数据后,写入密文表。创建表t_plain存储明文数据和表t_enc存储密文数据。

    -- DROP EXTENSION encdb;
    CREATE TABLE t_plain(
        id int,
        name varchar(20),
        introduction text
    ) distributed BY (id);
    
    INSERT INTO t_plain VALUES (1, 11, 'aaa');
    
    CREATE TABLE t_enc(
        id int,
        name varchar(20),
        introduction bytea
    ) distributed by (id);
    
    INSERT INTO t_enc 
    SELECT id ,name, sm4_encrypt_text(introduction,'passwd') FROM t_plain;
    
    SELECT * FROM t_enc;

    introduction字段的值已被加密,返回信息如下。

     id | name |            introduction
    ----+------+------------------------------------
      1 | 11   | \x0ca8e6c45a83e98efe99dcde0510930e
    (1 row)

解密

使用SM4函数查询加密字段语法如下。

-- 解密text格式数据
sm4_decrypt_text(data bytea, password text)

-- 解密varchar格式数据
sm4_decrypt_varchar(data bytea, password text)

参数说明如下。

参数

说明

data bytea

需要解密的Bytea类型的数据。

password text

加密密钥,为Text格式。

  • 示例一:对上文加密的字段进行解密,示例如下。

    SELECT sm4_decrypt_text('\x308b71cc7fa0de7d720b2c394a3a83c2'::bytea, 'key');

    解密的内容为who am i,返回信息如下。

     sm4_decrypt_text
    ------------------
     who am i
    (1 row)
  • 示例二:使用SM4函数解密查询密文表t_enc

    SELECT id, name, sm4_decrypt_text(introduction,'passwd') FROM t_enc;

    introduction字段的值已解密,返回信息如下。

    id | name | sm4_decrypt_text
    ----+------+------------------
      1 | 11   | aaa
    (1 row)

相关文档

pgcrypto的详细信息,请参见postgresql