0
点赞
收藏
分享

微信扫一扫

pgcrypto

求索大伟 1天前 阅读 1

瀚高数据库
目录
环境
文档用途
详细信息

环境
系统平台:Linux x86-64 Red Hat Enterprise Linux 7
版本:14
文档用途
本文详细介绍pgcrypto。

详细信息

1、简介

pgcrypto是PostgreSQL的一个扩展模块,用于提供加密和密码散列功能。它扩展了 PostgreSQL 的功能,使其能够执行各种加密操作,包括对数据进行加密、生成密码散列以及其他与数据安全相关的功能。

pgcrypto提供了对称加密(symmetric encryption)和非对称加密(asymmetric encryption)的支持。对称加密用于加密和解密数据,而非对称加密用于创建和验证数字签名。这样就可以在数据库中存储加密数据,从而增加数据的安全性。只有具有相应权限的用户才能够解密数据。

pgcrypto 可以生成密码的散列(hash),这就可以在数据库中存储密码的散列值而不是密码明文。通过将用户密码的散列存储在数据库中,可以提高数据安全性。

pgcrypto支持数字签名和验证功能,可以创建数字签名以证明数据的完整性和来源,然后验证签名以确保数据未被篡改。

pgcrypto可以用于保护数据库中的敏感数据,如社会安全号码、信用卡号码等。通过对这些数据进行加密,即使数据库被未经授权的访问,也不会泄漏敏感信息。

PostgreSQL源码自带pgcrypto功能,而且从PostgreSQL 13开始,它被视为“受信任的”模块,可以使用对当前数据库具有CREATE权限的非超级用户安装。

2、安装配置

PostgreSQL官网提供的安装包已经编译好了此模块,登录数据库创建EXTENSION即可;源码编译安装的,先查询pg_available_extension_versions看是否存在pgcrypto,不存在则在源码包contrib/pgcrypto下编译安装,然后创建EXTENSION,命令如下:

[root@localhost pgcrypto]# pwd

/home/postgis/postgresql-15.4/contrib/pgcrypto

[root@localhost pgcrypto]# make install

postgres=# create extension pgcrypto;

CREATE EXTENSION

创建EXTENSION后默认会在public下创建很多功能函数。

3、pgcrypto详细功能

pgcrypto模块向PostgreSQL提供加密函数,用于加密和解密数据,以及执行与密码学相关的操作;强大的加密功能,使得用户可以在数据库层面更安全地处理敏感数据。使用户可以在数据库级别实现数据的安全性和隐私保护,而不必依赖于应用程序层面的加密;对 于需要存储敏感信息的应用程序和系统来说非常有用。

pgcrypto提供的函数类型有:通用哈希函数,密码哈希函数,PGP加密函数,原始加密函数,随机数据函数。

3.1 通用哈希函数(General Hashing Functions)

此类函数通常用于处理数据的摘要计算和消息身份验证,pgcrypto提供的函数有:

1)digest()

digest(data text, type text) returns bytea

digest(data bytea, type text) returns bytea

digest函数用于计算数据的哈希值,也称为消息摘要。哈希值是一个固定长度的二进制字符串,它是根据输入数据计算得出的,即使输入数据有微小的变化,哈希值也会有显著的不同。主要就是验证数据的完整性和唯一性。它可以帮助确保数据在传输或存储过程中没有被篡改,并且允许快速比较大量数据以查找相同的数据块。

示例1:以下是一个使用digest()函数计算哈希值的示例。

postgres=# SELECT digest('Hello World!', 'sha256');

                           digest

-----------------------------------------------------------

\x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069



postgres=# SELECT digest('Hello World!', 'md5');

               digest

------------------------------------

 \xed076287532e86365e841e92bfc50d8c

支持的算法包括md5、sha1、sha224、sha256、sha384、sha512,如果使用了OpenSSL,则可以支持更多的算法。

2)hmac()

hmac(data text, key text, type text) returns bytea

hmac(data bytea, key bytea, type text) returns bytea

hmac函数用于计算数据基于密钥的哈希值,也称为消息身份验证码(HMAC)。它使用一个密钥来计算数据的哈希值,并使用密钥来增加数据的安全性,以确保数据的完整性和来源。提供了密钥管理和数据完整性验证的一种方式。对于安全通信和验证来自受信任源的数据非常有用。

示例2:以下是一个使用 hmac函数计算哈希值的示例。

postgres=# SELECT hmac('Hello World!', 'secret_key','md5');

            hmac

------------------------------------

\x353f16791bf230dcaf1a318d9e2f7fd9

3.2 密码哈希函数(Password Hashing Functions)

此类函数用于安全地存储和验证用户密码,通常采用特定方法,以确保密码不以明文形式存储,从而提高安全性。提供的函数有crypt()和gen_salt():

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

crypt(password text, salt text) returns text

示例3:使用gen_salt生成一个“密钥”,crypt引用“密钥”对密码进行加密。

postgres=# select gen_salt('bf');

         gen_salt

-------------------------------

$2a$06$A4966wmBLFyPOeqNxq.1c.

postgres=# select crypt('password',gen_salt('bf'));

                       crypt

------------------------------------------------------

$2a$06$x4Ygy9f54IoqPG2r2teSMOYSRUym0ItTCUg9041j57iNYX1T.clTe

gen_salt函数用于生成一个“密钥”,作为crypt函数进行密码哈希计算的一个参数,目的是使相同的密码在每次哈希时产生不同的哈希值,增强密码的安全性。gen_salt根据指定的算法标识符作为参数,生成相应的“密钥”。crypt使用这个“密钥”进行哈希,从而生成安全的哈希密码。

gen_salt支持的参数是固定的几个算法标识符,包括:

bf (Blowfish):Blowfish 是一种对称密码算法,通常用于密码哈希而不是加密数据。

md5 (MD5):常见的哈希算法,但现在很多场景都认为MD5算法不安全,容易受到暴力攻击。

xdes (Extended DES):Extended DES是DES(Data Encryption Standard)的扩展版本。

des (DES - Data Encryption Standard):比较老的对称密码算法。

在实际应用中,你通常会先使用gen_salt生成“密钥”,然后将“密钥”与密码一起传递给crypt函数,以生成密码的哈希值。这种做法确保每个用户的密码都有不同的哈希值,并提高了密码的安全性。

3.3 PGP加密函数(PGP Encryption Functions)

这部分函数基于OpenPGP(RFC 4880,PGP: Pretty Good Privacy)标准实现了加密,支持对称密钥和公钥加密。OpenPGP 是一种用于数据加密和数字签名的标准,通常用于保护通信的机密性和完整性。这类函数包括:

1) 对称密钥加解密

pgp_sym_encrypt(data text, psw text) returns bytea

pgp_sym_encrypt_bytea(data bytea, psw text) returns bytea

pgp_sym_decrypt(msg bytea, psw text) returns text

pgp_sym_decrypt_bytea(msg bytea, psw text) returns bytea

pgp_sym_encrypt用于使用对称密钥加密数据,而pgp_sym_decrypt用于解密已加密的数据。这些函数可以在数据库中加密和解密数据,使用相同的对称密钥来保护数据的机密性。

示例4:使用pgp_sym_encrypt加密,pgp_sym_decrypt使用解密。

pg=# SELECT pgp_sym_encrypt('Hello, world', 'my_secret_key');                                                              pgp_sym_encrypt

------------------------------------

\xc30d0407030207639f8a0b1c9d9a7dd23d01325b92a8f85a2ba88a417cf81ed0546a0789b8dabb395bea7f67c7d5387a932c31700bb9c3ba492a9755ea7978919bd82388132a3c12d49f0af75306

pg=# SELECT pgp_sym_decrypt('\xc30d0407030207639f8a0b1c9d9a7dd23d01325b92a8f85a2ba88a417cf81ed0546a0789b8dabb395bea7f67c7d5387a932c31700bb9c3ba492a9755ea7978919bd82388132a3c12d49f0af75306', 'my_secret_key');

 pgp_sym_decrypt

-----------------

 Hello, world

2) 公钥加解密相关函数

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

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

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

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

armor(data bytea [ , keys text[], values text[] ]) 

dearmor(data text) returns bytea

pgp_key_id(bytea)

pgp_pub_encrypt使用公钥加密数据,pgp_pub_decrypt用于解密使用公钥加密的数据。其中加密操作使用接收方的公钥进行加密,只能由拥有相应私钥的接收方解密。通常用于安全地共享数据,确保只有指定接收方能够解密数据。

dearmor函数将文本类型解包为PGP ASCII-armor格式,armor功能相反;pgp_key_id是从ASCII-armor格式的密钥中提取密钥ID。

示例5:使用公钥加密,私钥解密的全过程。

–使用gpg生成密钥,过程中需要输入管理密钥的密码等多个操作

[root@local]#  gpg --gen-key

[root@local]#  gpg --list-secret-keys

[root@local]#  gpg -a --export KEYID > public.key

[root@local]#  gpg -a --export-secret-keys KEYID > secret.key

--此时在当前目录下会生成public.key和secret.key,生成的key很长,我们将其插入数据库保存为text,方便使用

--使用dearmor()将密钥key转为bytea格式

postgres=# select dearmor(pk) from pgp_key;



--使用pgp_key_id()提取密钥ID

postgres=# select pgp_key_id(dearmor(pk)) from pgp_key;

    pgp_key_id

------------------

 5328EEB323D49797

 5328EEB323D49797



--pgp_pub_encrypt加密

postgres=# select  pgp_pub_encrypt('Hello World!',dearmor(pk)) from pgp_key where c1 = 'public';



--pgp_pub_decrypt解密

postgres=# with t as (

select pgp_pub_encrypt('Hello World!',dearmor(pk)) as pub 

from pgp_key 

where c1 = 'public'

)

select pgp_pub_decrypt(t.pub,dearmor(pk)) 

from t, pgp_key 

where c1 = 'secret';

3.4 “原文”加密函数(Raw Encryption Functions)

此类函数使用用户提供的密钥执行加密操作,不会对密钥进行操作;不会检查数据完整性,也无法保证数据在传输或存储过程中不被篡改;随着PGP加密功能的引入,不推荐再使用这类函数。

但这些函数使用简单以及实际的安全性,这些函数成为最常用的函数,包括:

encrypt(data bytea, key bytea, type text)

decrypt(data bytea, key bytea, type text)



encrypt_iv(data bytea, key bytea, iv bytea, type text) 

decrypt_iv(data bytea, key bytea, iv bytea, type text)

  示例6:使用encrypt加密,使用decrypt解密。

postgres=# select encrypt('Hello World!'::bytea,

'key'::bytea,

'bf');

postgres=# select decrypt(

encrypt('Hello World!'::bytea,'key'::bytea,'bf'),  

'key'::bytea,  

'bf'::text)::text;

3.5 随机数据函数(Random-Data Functions)

这些函数用于生成随机数据,返回uuid或bytea类型, 随机数据在密码学、模拟和许多其他计算领域都有广泛的应用。UUID是128位长,通常表示为32个十六进制字符(包括连字符)。这些随机数通常具有唯一性,一般用于数据库表的主键,或任何需要唯一标识符的场景,这些函数包括:

gen_random_bytes(count integer) returns bytea

gen_random_uuid() returns uuid

gen_random_bytes()函数用于生成加密密钥、初始化向量(IV)等需要高质量随机数据的场景;gen_random_uuid()用于生成uuid,生成唯一的字符串。

示例7:生成随机数据

postgres=# SELECT gen_random_bytes(10);

    gen_random_bytes

------------------------

 \x715c54f2564f778c58e6

postgres=# select gen_random_uuid();

           gen_random_uuid

--------------------------------------

 f15f7743-c37d-4c75-977e-c974374685a7

4、最佳实践

pgcrypto提供的一系列函数,为PostgreSQL提供了强大的数据加密功能,使PostgreSQL能够满足各种数据安全场景的保密要求。

pgcrypto针对密码学操作提供了广泛使用的算法,包括AES、RSA、SHA-2等,这些算法经过广泛测试和验证,能够提供高度的数据安全性。它与数据库引擎紧密集成,充分利用了数据库的安全特性。由于与PostgreSQL高度集成,pgcrypto 可以充分利用数据库性能。

pgcrypto提供的函数对于初学者来说相对复杂,无法实现开箱即用,导致它用户很少,或只是使用了相对简单的一些功能;一些只是对密码加密的场景,用户在应用端加密要比在数据库端加密容易的多。数据的加解密操作必然会浪费一定的硬件资源,对于大体量数据场景,需要小心谨慎,否则会严重影响性能或导致更大的问题。

5、卸载

pgcrypto功能是PostgreSQL源码自带,因此pgcrypto EXTENSION的卸载,只需移除EXTENSION,移除前请确认是否还依赖pgcrypto提供的所有对象,移除时会把这些对象全部移除。

操作命令:

--删除extension

drop extension pgcrypto;
举报
0 条评论