业务需求需要对一些敏感数据进行加密处理,说到加密,分为非对称加密和对称加密,稍微解释一下这两个名词
1.对称加密方法,指加密和解密使用同一把密钥的方法。优势是加密速度快,缺陷是密钥只有一把,安全性较低。
oracle数据库加密有透明数据加密,这个是从10g就有了,需要了解可以转到下面链接
https://docs.oracle.com/cd/B19306_01/network.102/b14268/asotrans.htm#ASOAG600
下面介绍一下postgresql服务端加密插件pgcrypto
1.安装插件
create extension pgcrypto;
2.加密函数实例
一般哈希加密函数
digest()函数
digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea
举例:
可以使用不同的加密算法
hmac(data text, key text, type text) returns bytea
hmac(data bytea, key text, type text) returns bytea
用key计算hash值,type和digest一样,hmac和digest类似,但是只有早知道key的情况下才能计算出哈希值,
这样可以预防更改数据以及更改哈希匹配的情况,如果key大于hash block size,那么先计算哈希值,哈希值作为key使用
举例:
摘除十六进制标识
密码哈希函数
crypt()和gen_salt()专用于密码哈希加密,crypt()计算哈希值, gen_salt()为crypt()提供算法参数,gen_salt()是随机产生一个值并传递给crypt()使用
在以下几个方面,crypt()与MD5,sha1的哈希算法不同
1.crypt()加密算法比较慢,因为数据量很小,这就是使得暴力破解密码比较难的一种方法。换句话说,就是说使用crypt()加密,比较安全,很难用暴力破解密码。
2. gen_salt()产生随机值,因此即使密码一样,加密后的密码也会不一样。
3.在结果中包含了算法类型,因此不同算法的哈希密码可以共存
1.对称加密方法,指加密和解密使用同一把密钥的方法。优势是加密速度快,缺陷是密钥只有一把,安全性较低。
2.非对称加密方法,指加密和解密用到一对钥匙,一把为私钥,一把为公钥。通常的用法是公钥用于加密,私钥用于解密,当然也可以私钥加密,公钥解密。比如乙方用公钥进行加密后,发送数据到甲方,甲方用自己的私有密钥解密,就算传输过程中,数据被截取,甚至公钥被拿到,没有私钥,还是无法解密,这种加密的优势是更加安全,你自己只要保护好私钥,就可以保证别人给你发的数据无法被篡改、窃听。这种加密方式的效率和对称加密相比,效率会差。
oracle数据库加密有透明数据加密,这个是从10g就有了,需要了解可以转到下面链接
https://docs.oracle.com/cd/B19306_01/network.102/b14268/asotrans.htm#ASOAG600
下面介绍一下postgresql服务端加密插件pgcrypto
1.安装插件
create extension pgcrypto;
2.加密函数实例
一般哈希加密函数
digest()函数
digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea
标准算法支持md5, sha1, sha224, sha256, sha384 and sha512,如果编译时有OpenSSL选项,那么会有更多的算法支持,见下表
Functionality | Built-in | With OpenSSL |
---|---|---|
MD5 | yes | yes |
SHA1 | yes | yes |
SHA224/256/384/512 | yes | yes (Note 1) |
Other digest algorithms | no | yes (Note 2) |
Blowfish | yes | yes |
AES | yes | yes (Note 3) |
DES/3DES/CAST5 | no | yes |
Raw encryption | yes | yes |
PGP Symmetric encryption | yes | yes |
PGP Public-Key encryption | yes | yes |
举例:
可以使用不同的加密算法
hank=# select digest('I like the girl who is pretty', 'md5');
digest
------------------------------------
\x9ce35f7b9938e4416fece04ed4638cab
hank=# select digest('I like the girl who is pretty', 'sha1');
digest
--------------------------------------------
\xb8995c8638cb995d15b8b99a7597c6fd75436770
(1 row)
hank=# select digest('I like the girl who is pretty', 'sha224');
digest
------------------------------------------------------------
\x9c18ee740b10abff52c7b4acb1caec46b294f12bc9a9bdb7916a4a27
如果想要摘除十六进制标识,可以使用encode,如下结果中就没有\x了
hank=# select encode(digest('I like the girl who is pretty', 'md5'),'hex');
encode
----------------------------------
9ce35f7b9938e4416fece04ed4638cab
hmac()函数
hmac(data text, key text, type text) returns bytea
hmac(data bytea, key text, type text) returns bytea
用key计算hash值,type和digest一样,hmac和digest类似,但是只有早知道key的情况下才能计算出哈希值,
这样可以预防更改数据以及更改哈希匹配的情况,如果key大于hash block size,那么先计算哈希值,哈希值作为key使用
举例:
hank=# select hmac('I like the girl who is pretty', 'this is a key','md5');
hmac
------------------------------------
\x0e5e3d552c2fc9b24761d1e1efc78d93
(1 row)
hank=# select hmac('I like the girl who is pretty', 'this is a key','sha1');
hmac
--------------------------------------------
\xb4f5c456bb142ff608d1d40f1563ec6dbdb6a7f9
(1 row)
hank=# select hmac('I like the girl who is pretty', 'this is a key','sha256');
hmac
--------------------------------------------------------------------
\x3f3a9c8b367f84facc3899187ba60f00daf0d5d0d768b6526ac3d545b330959d
摘除十六进制标识
hank=# select encode(hmac('I like the girl who is pretty', 'this is a key','sha1'),'hex');
encode
------------------------------------------
b4f5c456bb142ff608d1d40f1563ec6dbdb6a7f9
密码哈希函数
crypt()和gen_salt()专用于密码哈希加密,crypt()计算哈希值, gen_salt()为crypt()提供算法参数,gen_salt()是随机产生一个值并传递给crypt()使用
在以下几个方面,crypt()与MD5,sha1的哈希算法不同
1.crypt()加密算法比较慢,因为数据量很小,这就是使得暴力破解密码比较难的一种方法。换句话说,就是说使用crypt()加密,比较安全,很难用暴力破解密码。
2. gen_salt()产生随机值,因此即使密码一样,加密后的密码也会不一样。
3.在结果中包含了算法类型,因此不同算法的哈希密码可以共存
4.其中一些是自适应的,意味着,当计算机变得更快时,你可以调整该算法变得更慢,而不会产生与现有口令的不兼容。crypt(password text, salt text) returns text
gen_salt(type text [, iter_count integer ]) returns text
crypt支持的算法
Algorithm | Max Password Length | Adaptive? | Salt Bits | Output Length | Description |
---|---|---|---|---|---|
bf | 72 | yes | 128 | 60 | Blowfish-based, variant 2a |
md5 | unlimited | no | 48 | 34 | MD5-based crypt |
xdes | 8 | yes | 24 | 20 | Extended DES |
des | 8 | no | 12 | 13 | Original UNIX crypt |
crypt()迭代次数
Algorithm | Default | Min | Max |
---|---|---|---|
xdes | 725 | 1 | 16777215 |
bf | 6 | 4 | 31 |
xdes额外限制,只能是奇数
bf最小是4,最大31,一定要注意
假设密码由大小写字母以及数字组成,8个字符密码所有字符组合所需要的时间
哈希算法速度
Algorithm | Hashes/sec | For [a-z] | For [A-Za-z0-9] | Duration relative to md5 hash |
---|---|---|---|---|
crypt-bf/8 | 1792 | 4 years | 3927 years | 100k |
crypt-bf/7 | 3648 | 2 years | 1929 years | 50k |
crypt-bf/6 | 7168 | 1 year | 982 years | 25k |
crypt-bf/5 | 13504 | 188 days | 521 years | 12.5k |
crypt-md5 | 171584 | 15 days | 41 years | 1k |
crypt-des | 23221568 | 157.5 minutes | 108 days | 7 |
sha1 | 37774272 | 90 minutes | 68 days | 4 |
md5 (hash) | 150085504 | 22.5 minutes | 17 days | 1 |
实例:
hank=# select crypt('this is my password', gen_salt('xdes',4));
ERROR: gen_salt: Incorrect number of rounds
hank=# select crypt('this is my password', gen_salt('xdes',5));
crypt
----------------------
_3...btBSoVwmTmPniTs
hank=# select crypt('this is my password', gen_salt('md5'));
crypt
------------------------------------
$1$foh3.pi4$RhO.ftFCiVT3aCiJYy.U6/
hank=# select crypt('this is my password', gen_salt('md5'));
crypt
------------------------------------
$1$2PG7y.ZR$nDITGLovK2qK3ETHApL2I0
hank=# select crypt('this is my password', gen_salt('bf',4));
crypt
--------------------------------------------------------------
$2a$04$Asyqp8HL/3pfj.AsnZN00.zFjWrS6RHqtpsz6P57SXUv2hfi/R2zG
建表测试:
create table t_pwd(id int primary key, pwd text);
insert into t_pwd(id,pwd) values (1, crypt('this is a pwd', gen_salt('bf',8)));
hank=# select * from t_pwd;
id | pwd
----+--------------------------------------------------------------
1 | $2a$08$Zw.beTeVnu8e2P3q9cZs5OImLhYYe4IICS7Lgf4GlDcdF9A9bTbO6
(1 row)
解密测试:
hank=# select * from t_pwd where pwd=crypt('this is a pwd',pwd);
id | pwd
----+--------------------------------------------------------------
1 | $2a$08$Zw.beTeVnu8e2P3q9cZs5OImLhYYe4IICS7Lgf4GlDcdF9A9bTbO6
(1 row)
hank=# select * from t_pwd where pwd=crypt('this',pwd);
id | pwd
----+-----
(0 rows)
以下测试可见,空格一定不要忽略掉,否则也是返回false
hank=# select crypt('this is a error pwd source', pwd)=pwd from t_pwd where id =1;
?column?
----------
f
(1 row)
hank=# select crypt('this is a pwd ', pwd)=pwd from t_pwd where id =1;
?column?
----------
f
(1 row)
hank=# select crypt('this is a pwd', pwd)=pwd from t_pwd where id =1;
?column?
----------
t
(1 row)