Oracle中的加密算法
加密算法概述
在介绍oracle中的加密算法之前,大家首先要对加密算法有一个大致的了解,懂得为什么加密,如何加密,加密算法的分类。
一, 为什么加密
我们的系统中会存在一些极其敏感的数据,这些数据涉及到公司的机密。自然这些是不想让其他公司或竞争对手看到的,所以就需要一种方法来对数据进行“包装”。包装后的数据就象是增加了一层坚固的外壳,其他人很难看到壳内的敏感数据。这种“包装”就是加密。可见加密对于敏感数据的重要意义。
二, 如何加密
所谓“加密”,就是对原内容为明文的文件或数据按某种算法进行处理,使其成为不可读的代码,经过这样处理的数据通常称为“密文”,密文只能在经过相对应的反向算法处理后才能恢复原来的内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的,而将该编码信息转化为其原来数据的过程,就是“解密”。
最简单的加密就是通过改变明文中的字符位置来实现。举个简单的例子,比如说welcome这个字符串,我通过交换相邻位置的字符位置来实现最简单的加密。加密后的字符串变成ewclmoe。这是简单的加密方式,可以说没有任何的安全性,但是可以说明加密的原理,就是通过一定的处理让明文转变成很难读懂的密文。
现在流行的加密算法是利用一复杂的密钥通过某种加密的算法将明文转化为密文。既然是进行加密,那么和加密相关的密钥和加密算法自然也是需要保护的。算法的保密性可以分为基于保持算法的秘密和基于保持密钥的秘密。
如果算法的保密性是基于保持算法的秘密,这种算法称为受限制的算法。受限制的算法具有历史意义,但按现在的标准,它们的保密性已远远不够。大的或经常变换的用户组织不能使用它们,因为每有一个用户离开这个组织,其它的用户就必须改换另外不同的算法。如果有人无意暴露了这个秘密,所有人都必须改变他们的算法。
更糟的是,受限制的密码算法不可能进行质量控制或标准化。每个用户组织必须有他们自己的唯一算法。这样的组织不可能采用流行的硬件或软件产品。但窃听者却可以买到这些流行产品并学习算法,于是用户不得不自己编写算法并予以实现,如果这个组织中没有好的密码学家,那么他们就无法知道他们是否拥有安全的算法。
而基于保持密钥的算法则具有更大的灵活性和实用习性。这些算法的安全性都基于密钥的安全性;而不是基于算法的细节的安全性。这就意味着算法可以公开,也可以被分析,可以大量生产使用算法的产品,即使偷听者知道你的算法也没有关系;如果他不知道你使用的具体密钥,他就不可能阅读你的消息。
演示如下,密钥用K表示。K可以是很多数值里的任意值。密钥K的可能值的范围叫做密钥空间。加密和解密运算都使用这个密钥(即运算都依赖于密钥,并用K作为下标表示),这样,加/解密函数现在变成:
EK(M)=C
DK(C)=M.
这些函数具有下面的特性:
DK(EK(M))=M.
有些算法使用不同的加密密钥和解密密钥,也就是说加密密钥K1与相应的解密密钥K2不同,在这种情况下:
EK1(M)=C
DK2(C)=M
DK2 (EK1(M))=M
三, 加密算法的分类
1, 基于“消息摘要”算法
“消息摘要”(Message Digest)是一种能产生特殊输出格式的算法,这种加密算法的特点是无论用户输入什么长度的原始数据,经过计算后输出的密文都是固定长度的,这种算法的原理是根据一定的运算规则对原数据进行某种形式的提取,这种提取就是“摘要”,被“摘要”的数据内容与原数据有密切联系,只要原数据稍有改变,输出的“摘要”便完全不同,因此基于这种原理的算法便能对数据完整性提供较为健全的保障。但是,由于输出的密文是提取原数据经过处理的定长值,所以它已经不能还原为原数据,即消息摘要算法是“不可逆”的,理论上无法通过反向运算取得原数据内容,因此它通常只能被用来做数据完整性验证,而不能作为原数据内容的加密方案使用,否则谁也无法还原。尽管如此,“消息摘要”算法还是为密码学提供了健全的防御体系,因为连专家也无法根据拦截到的密文还原出原来的密码内容。因为这个特性,“消息摘要”算法产生的密文被称为“摘要”。
如今常用的“消息摘要”算法经历了多年验证发展而保留下来的强者,分别是MD2、MD4、MD5、SHA、SHA-1/256/383/512等,其中最广泛应用的是基于MD4发展而来的MD5算法。
注:在oracle的加密包dbms_obfuscation_toolkit提供了MD5算法的调用过程。就象上面说明的那样,MD5这种基于消息摘要的加密算法只是单向的,是不可逆的,只能作为一种数据完整性的严整方法。另外一点,一般来说这类算法都是不需要密钥的。
2,“对称/非对称密钥”加密算法
由于“消息摘要”算法产生的数据只能作为一种身份验证的凭证来使用,如果我们要对整个文档数据进行加密,就不能采用这种“不可逆”的算法了,因此“密钥”算法(Key Encoding)的概念被提出,与开头提到的智力题类似,此类算法通过一个被称为“密钥”的凭据进行数据加密处理,接收方通过加密时使用的“密钥”字符串进行解密,即双方持有的“密码”相同(对称)。如果接收方不能提供正确的“密钥”,解密出来的就不是原来的数据了。
以上是“对称密钥”的概念,那么“非对称密钥”又该怎么理解呢?有人用邮箱作为比喻,任何人都可以从邮箱的信封人口塞进信件,但是取信的权力却仅仅在于持有邮箱钥匙的人的手上。这个众人皆知的信封入口就是“公钥”(Public Key),而你持有的邮箱钥匙就是“私钥”(Private Key),这种算法规定,对方给你发送数据前,可以用“公钥”加密后再发给你,但是这个“公钥”也无法解开它自己加密的数据,即加密过程是单向的,这样即使数据被途中拦截,入侵者也无法对其进行破解,能还原数据内容的只有“私钥”的持有者,这就是“非对称密钥”加密算法,也称为“公共密钥算法”,这两者均建立在PKI验证体系结构上。
基于“对称密钥”的加密算法有DES、TripleDES、RC2、RC4、RC5和Blowfish等;基于“非对称密钥”的加密算法有RSA、Diffie-Hellman等。
注:在oracle的加密包dbms_obfuscation_toolkit提供了DES、TripleDES(3-DES)的算法。
Oracle中的加密算法
Oracle的加密包dbms_obfuscation_toolkit提供三种加密的算法,其中包括基于“消息摘要”的算法MD5,还有对称的加密算法DES和DES3。
1,MD5
前面已经介绍过了MD5不能作为常规的加密使用,他只能作为一种校验数据完整性的方法。
加密包dbms_obfuscation_toolkit中提供了四个关于MD5算法的过程或者函数,两个是操作RAW型数据的,另外两个是操作VARCHAR2。下面主要介绍下对VARCHAR2进行加密的MD5过程PROCEDURE MD5。
PROCEDURE MD5
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
INPUT_STRING VARCHAR2 IN
CHECKSUM_STRING VARCHAR2(16) OUT
其中参数INPUT_STRING为预加密的输入字符串,CHECKSUM_STRING为加密后的输出字符串。
参考代码如下:
例子1:
SQL> variable n_in varchar2(100)
SQL> variable n_out varchar2(100)
SQL> exec :n_in := 'this is a jok!'
SQL> exec dbms_obfuscation_toolkit.MD5(INPUT_STRING => :n_in,CHECKSUM_STRING => :n_out);
PL/SQL procedure successfully completed.
SQL> print n_out
N_OUT
----------------
š'Öž†å,(3ÐÜY
SQL> select length(:n_out) from dual;
LENGTH(:N_OUT)
--------------
16
例子2:
SQL> exec :n_in := 'a';
SQL> exec dbms_obfuscation_toolkit.MD5(INPUT_STRING => :n_in,CHECKSUM_STRING => :n_out);
PL/SQL procedure successfully completed.
SQL> print n_out
N_OUT
-------------------------------------------------
Áu¹Àñ¶¨1Ùâiw&a
SQL> select length(:n_out) from dual;
LENGTH(:N_OUT)
--------------
16
例子3:
SQL> exec :n_in := 'a';
SQL> exec dbms_obfuscation_toolkit.MD5(INPUT_STRING => :n_in,CHECKSUM_STRING => :n_out);
PL/SQL procedure successfully completed.
SQL> print n_out
N_OUT
-------------------------------------------------
Áu¹Àñ¶¨1Ùâiw&a
SQL> select length(:n_out) from dual;
LENGTH(:N_OUT)
--------------
16
说明:
(1) 对于例子1我加密的字符串长度大概是15,而例子2中我加密的字符串长度为1,可见MD5对加密字符串的长度是没有限制,当然了VARCHAR2自身会有4000的限制。
(2) 从3个例子的结果可以看出来,无论加密前的字符串长度为多少,加密后的字符串长度均为16。这个是由MD5的算法决定的,这也是为什么MD5仅仅是“摘要”的体现,他是不可逆的。
(3) 例子2和例子3看起来完全一样,这个是很好理解的,同样的输入当然得到同样的结果了。这也是MD5可以作为一种数据检验方法的基础,同样的输入同样的输出。反过来呢,同样的输出是否代表同样的输入呢?总有一些例外的,不过几率是极小的,比连续3期都中双色球头奖还要难。
(4) MD5可以作为一种数据校验的方法,如果数据量比较大的话,那么执行的效率就是个需要考虑的问题了。
2,DES
DES是一种较为强壮的数据加密算法,他的算法是公开的,全部的保密性都在于密钥的保密性上。所以对于DES(包括DES)来说一个复杂的密钥是必须的,简单的密钥对于那些黑客来说形同虚设。现在的机器性能相比原来有了极大的提高,这也给暴力破解提供的物质上的准备。只要有足够的时间,一切密文都会被破解的。我们能做得就是采用极其复杂的密钥,将这个破解的时间往后推100年,推1000年,甚至10000年,让破解密文后得到的回报远远小于破解所需的花费。想一想,如果破解一个软件的注册码需要花费100万元,而购买注册证书的花费只有100元,大部分人都不会舍易取难了吧。当然了,也不排除那些极其执着的技术狂人,但毕竟是极小数。对于DES现在唯一的破解办法就是穷举法,如果一台计算机的速度是每一秒种检测一百万个密钥,那么它搜索完全部密钥就需要将近2285年的时间。那么那些技术狂人可以活这么久么?
Oracle的加密包dbms_obfuscation_toolkit中提供了实用与RAW类型的DES加密,也提供了VARCHAR2类型的DES加密。下面只介绍VARCHAR2类型的加密,RAW的与此类似。
PROCEDURE DESGETKEY
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
SEED_STRING VARCHAR2 IN
KEY VARCHAR2 OUT
通过调用过程DESGETKEY可以产生一个相对复杂的密钥。其中参数SEED_STRING是产生密钥需要的种子,KEY为系统产生的密钥字符串。
例子1:
SQL> variable n_seed varchar2(100)
SQL> variable n_key varchar2(100)
SQL> exec :n_seed := 'sun'
SQL> exec dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key);
BEGIN dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key); END;
*
ERROR at line 1:
ORA-28237: seed length too short
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 3
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 25
ORA-06512: at line 1
例子2:
SQL> exec :n_seed := 'sunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwg'
SQL> exec dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key);
BEGIN dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key); END;
*
ERROR at line 1:
ORA-28237: seed length too short
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 3
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 25
ORA-06512: at line 1
例子3:
SQL> exec :n_seed := 'sunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwg'
SQL> exec dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key);
PL/SQL procedure successfully completed.
SQL> print n_key
N_KEY
-------------------------------------------------
Æs˜[È*n
SQL> select length(:n_key) from dual;
LENGTH(:N_KEY)
--------------
8
例子4:
SQL> exec :n_seed := 'sunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwg'
SQL> exec dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key);
PL/SQL procedure successfully completed.
SQL> print n_key
N_KEY
-------------------------------------------------
©ÿëíŒJw
例子5:
SQL> exec :n_seed := 'sunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwgsunwg'
SQL> exec dbms_obfuscation_toolkit.DESGETKEY(SEED_STRING => :n_seed,key => :n_key);
PL/SQL procedure successfully completed.
SQL> print n_key
N_KEY
-------------------------------------------------
XEÉš©”?y
SQL> select length(:n_key) from dual;
LENGTH(:N_KEY)
--------------
8
说明:
(1) 例子1中的种子长度为3,例子2中种子长度为70,这两种情况生成密钥失败;而例子3中种子的长度为80,成功执行。可见过程DESGETKEY对种子的长度有着严格限制,这应该也是为了产生更加可靠的密钥的需要吧。在我的oracle企业版10.02中这个长度的限制为80个字符。
(2) 例子3中的种子字符串和例子4中的相同,但是产生的密钥却完全不一样。这也是增加密钥可靠性的一种办法。同样的输入,不同的输出。
(3) 例子4的种子长度为80,产生的密钥长度为8;例子5中的种子长度为90,产生的密钥长度也为8。密钥的长度为8,是由DES的算法决定的(感兴趣的同学可以参考DES的具体算法)。
PROCEDURE DESENCRYPT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
INPUT_STRING VARCHAR2 IN
KEY_STRING VARCHAR2 IN
ENCRYPTED_STRING VARCHAR2 OUT
DESENCRYPT过程就是DES的加密过程。其中参数INPUT_STRING是需要加密的字符串,参数KEY_STRING是加密算法的密钥匙,而参数ENCRYPTED_STRING为得到的加密后的字符串。
例子1:
SQL> variable en_in varchar2(100)
SQL> variable en_key varchar2(100)
SQL> variable en_out varchar2(100)
SQL> exec :en_in := 'sunwg'
SQL> exec :en_key := '12345'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
BEGIN dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out); END;
*
ERROR at line 1:
ORA-28232: invalid input length for obfuscation toolkit
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 21
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 115
ORA-06512: at line 1
例子2:
SQL> exec :en_in := 'sunwgsun'
SQL> exec :en_key := '12345'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
BEGIN dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out); END;
*
ERROR at line 1:
ORA-28234: key length too short
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 21
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 115
ORA-06512: at line 1
例子3:
SQL> exec :en_in := 'sunwgsun'
SQL> exec :en_key := '12345678'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
PL/SQL procedure successfully completed.
SQL> print en_out
EN_OUT
-------------------------------------------------
6ð‚ªä5Ù
SQL> select length(:en_out) from dual;
LENGTH(:EN_OUT)
---------------
8
例子4:
SQL> exec :en_in := 'sunwgsun'
SQL> exec :en_key := '123456789'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
PL/SQL procedure successfully completed.
SQL> print en_out
EN_OUT
-------------------------------------------------
6ð‚ªä5Ù
SQL> select length(:en_out) from dual;
LENGTH(:EN_OUT)
---------------
8
例子5:
SQL> exec :en_in := 'sunwgsun'
SQL> exec :en_key := '12345678901234567890'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
PL/SQL procedure successfully completed.
SQL> print en_out
EN_OUT
-------------------------------------------------
6ð‚ªä5Ù
SQL> select length(:en_out) from dual;
LENGTH(:EN_OUT)
---------------
8
例子6:
SQL> exec :en_in := 'sunwgsunwg'
SQL> exec :en_key := '12345678'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
BEGIN dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out); END;
*
ERROR at line 1:
ORA-28232: invalid input length for obfuscation toolkit
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 21
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 115
ORA-06512: at line 1
例子7:
SQL> exec :en_in := 'sunwgsunwgsunwgs'
SQL> exec :en_key := '12345678'
SQL> exec dbms_obfuscation_toolkit.DESENCRYPT(INPUT_STRING => :en_in,KEY_STRING => :en_key,ENCRYPTED_STRING => :en_out);
PL/SQL procedure successfully completed.
SQL> print en_out
EN_OUT
-------------------------------------------------
6ð‚ªä5ÙŠõ©P‘ÏT£
SQL> select length(:en_out) from dual;
LENGTH(:EN_OUT)
---------------
16
说明:
(1) 从例子1和例子2可以看出输入的需要加密的字符串长度是有限制的,需要大于等于8的。那是不是所有大于8的都可以呢,不是的。从例子6可以看出长度是10也是不可以的,例子7说明长度是16是允许的。其实长度只要是8的倍数就可以,因为DES加密的第一步就是置位,置位的最少单位是64位,即8个字节。超过8个字符的也会被分割成多个长度为8的字符串进行处理。
(2) 关于加密密钥的长度大家都知道了,应该是不能小于8的,这点从例子2和例子3中也可以看出来。如果大于8呢,大于8也是允许的合法输入。可是从例子3,4,5可以看出来,密钥匙有效的只是前8个字符,后面的全部会被忽略的。所以超过8个字符的密钥也是没有意思的。从这里就可以体现出过程DESGETKEY的重要性了,他可以产生相对人为设置的更加复杂的密钥。
(3) 从例子3和例子7可以看出,加密后的字符串长度等于加密前的字符串长度,都是8的倍数。还是那句话,这是由DES的算法决定的。
PROCEDURE DESDECRYPT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
INPUT_STRING VARCHAR2 IN
KEY_STRING VARCHAR2 IN
DECRYPTED_STRING VARCHAR2 OUT
过程DESDECRYPT是DES的解密过程,使用方法和注意事项都和加密过程类型,这里就不在详细说明了。
3,DES3
DES3的过程和函数与DES的基本一样,只不过有的函数或者过程可能会多两个参数一个是WHICH,还有一个是IV_STRING。这两个参数都有默认值的,调用的时候使用默认值就没有问题。WHICH的默认值是TwoKeyMode,而IV_STRING的默认值是NULL。至于两个参数的具体含义就不大清楚了,估计WHICH参数说明的是DES3的加密方式是采用2个密钥进行3次加密。
总结:
上面大概介绍了一下加密的基本知识和oracle中的加密包dbms_obfuscation_toolkit。在实际的工作中,那些敏感的数据是需要保护的,而加密技术就是一种很好的保护数据的方法。希望大家的数据都是安全的。