瀚高数据库
目录
环境
文档用途
详细信息
环境
系统平台: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 installpostgres=# 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 byteadigest(data bytea, type text) returns bytea
digest函数用于计算数据的哈希值,也称为消息摘要。哈希值是一个固定长度的二进制字符串,它是根据输入数据计算得出的,即使输入数据有微小的变化,哈希值也会有显著的不同。主要就是验证数据的完整性和唯一性。它可以帮助确保数据在传输或存储过程中没有被篡改,并且允许快速比较大量数据以查找相同的数据块。
示例1:以下是一个使用digest()函数计算哈希值的示例。
postgres=# SELECT digest('Hello World!', 'sha256');digest-----------------------------------------------------------\x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069postgres=# SELECT digest('Hello World!', 'md5');digest------------------------------------\xed076287532e86365e841e92bfc50d8c
支持的算法包括md5、sha1、sha224、sha256、sha384、sha512,如果使用了OpenSSL,则可以支持更多的算法。
2)hmac()
hmac(data text, key text, type text) returns byteahmac(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 textcrypt(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 byteapgp_sym_encrypt_bytea(data bytea, psw text) returns byteapgp_sym_decrypt(msg bytea, psw text) returns textpgp_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------------------------------------\xc30d0407030207639f8a0b1c9d9a7dd23d01325b92a8f85a2ba88a417cf81ed0546a0789b8dabb395bea7f67c7d5387a932c31700bb9c3ba492a9755ea7978919bd82388132a3c12d49f0af75306pg=# 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 byteapgp_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()提取密钥IDpostgres=# select pgp_key_id(dearmor(pk)) from pgp_key;pgp_key_id------------------5328EEB323D497975328EEB323D49797--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 byteagen_random_uuid() returns uuid
gen_random_bytes()函数用于生成加密密钥、初始化向量(IV)等需要高质量随机数据的场景;gen_random_uuid()用于生成uuid,生成唯一的字符串。
示例7:生成随机数据
postgres=# SELECT gen_random_bytes(10);gen_random_bytes------------------------\x715c54f2564f778c58e6postgres=# 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提供的所有对象,移除时会把这些对象全部移除。
操作命令:
--删除extensiondrop extension pgcrypto;