利用Oracle的dbms_obfuscation_toolkit加密解密数据
<P >为保护敏感数据,oracle从8i开始提供一个数据加密包:dbms_ obfuscation _toolkit.利用这个包,我们可以对数据进行DES,Triple DES或者MD5加密,本文就此讲解如何使用以及使用过程需要注意的问题:<BR><B>1</B><B>、</B><B>dbms_obfuscation_toolkit</B><B>简介</B><B ><BR></B>dbms_obfuscation_toolkit主要有一下几个存储过程:<BR>DESGETKEY -- 产生密钥,用于DES算法 <BR>DES3GETKEY -- 产生密钥,用于Triple DES算法 <BR>DESENCRYPT -- 用DES算法加密数据<BR>DESDECRYPT -- 用DES算法解密数据<BR>DES3ENCRYPT -- 用Triple DES算法加密数据<BR>DES3DECRYPT -- 用DES算法解密数据<BR>MD5 -- 用MD5算法加密数据<o:p></o:p></P><P ><B>2</B><B>、准备数据表</B><B><o:p></o:p></B></P>
<P >在开始前,我们先创建表users:<o:p></o:p></P>
<P >drop table users;<BR> create table users(<BR> userid varchar2(50) primary key,<BR> password varchar2(64), --密码原文<BR> encrypted varchar2(64) --加密后的密码<BR> );<o:p></o:p></P>
<P >insert into users values ('user1','user1234',null);<BR>insert into users values ('user2','abcd1234',null);<BR>insert into users values ('user3','oracle12',null);<BR>commit;<o:p></o:p></P>
<P ><B>3</B><B>、创建包</B><B>PG_ENCRYPT_DECRYPT</B><B ><o:p></o:p></B></P>
<P >create or replace package PG_ENCRYPT_DECRYPT is<BR>iKey varchar2(8):='oracle9i';<BR>function GEN_RAW_KEY ( iKey in varchar2) return raw;<BR>function DECRYPT_3KEY_MODE(iValue in raw,iMode in pls_integer)return varchar2;<BR>function ENCRYPT_3KEY_MODE(iValue in varchar2,iMode in pls_integer)return raw;<BR>end;<BR>/<BR>create or replace package body PG_ENCRYPT_DECRYPT is<BR>function GEN_RAW_KEY ( iKey in varchar2) <BR>return raw<BR>as<BR>rawkey raw(240) := '';<BR>begin<BR>for i in 1..length(iKey) loop<BR> rawkey := rawkey||hextoraw(to_char(ascii(substr(iKey, i, 1))));<BR> end loop;<BR> return rawkey;<BR>end;<BR>/*<BR> Creating function DECRYPT_3KEY_MODE<BR>*/<BR><BR>FUNCTION DECRYPT_3KEY_MODE (<BR> iValue in raw, iMode in pls_integer<BR>)<BR>return varchar2<BR>as<BR>vDecrypted varchar2(4000);<BR>rawkey raw(240) := '';<BR>begin<BR>rawkey := GEN_RAW_KEY(iKey);<BR>-- decrypt input string<BR>vDecrypted := dbms_obfuscation_toolkit.des3decrypt (<BR>UTL_RAW.CAST_TO_VARCHAR2(iValue)<BR>, key_string => rawkey<BR>, which => iMode<BR>);<BR>return vDecrypted;<BR>end;<BR><BR>/*<BR>Creating function ENCRYPT_3KEY_MODE<BR>*/<BR><BR>FUNCTION ENCRYPT_3KEY_MODE (<BR> iValue in varchar2, iMode in pls_integer<BR>)<BR>return raw<BR>as<BR>vEncrypted varchar2(4000);<BR>vEncryptedRaw Raw(2048);<BR>rawkey raw(240) := '';<BR>begin<BR>rawkey := GEN_RAW_KEY(iKey);<BR>-- encrypt input string<BR>vEncrypted := dbms_obfuscation_toolkit.des3encrypt (<BR>iValue<BR>, key_string => rawkey<BR>, which => iMode<BR>);<BR>-- convert to raw as out<BR>vEncryptedRaw := UTL_RAW.CAST_TO_RAW(vEncrypted);<BR>return vEncryptedRaw;<BR>end;<BR>end;<o:p></o:p></P>
<P ><B >4</B><B >、测试</B><B ><o:p></o:p></B></P>
<P >在SQL Plus下输入:<o:p></o:p></P>
<P >SQL > update users set encrypted = PG_ENCRYPT_DECRYPT. ENCRYPT _ 3KEY_MODE (password,1);<BR>SQL > commit;<o:p></o:p></P>
<P >执行完以上SQL语句后,encrypted 存储的就是加密后的password字段.我们看一下结果:<o:p></o:p></P>
<P >SQL > select * from users;<BR>USERID PASSWORD ENCRYPTED <BR>------ --------- ----------------<BR>user1 user1234 69EF<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="a">3A</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="211" UnitName="a">211A</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0F</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="2" UnitName="C">2C</st1:chmetcnv>32<BR>user2 abcd1234 CF<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7562203" UnitName="F">7562203F</st1:chmetcnv>6CEDE5<BR>user3 oracle12 65D71D7148FA001D<o:p></o:p></P>
<P >这个加密结果是否正确?我们对加密结果解密就知道了,在SQL Plus下输入:<o:p></o:p></P>
<P >SQL > select<o:p></o:p></P>
<P >userid,password,PG_ENCRYPT_DECRYPT.DECRYPT_3KEY_MODE(encrypted,1) DECRYPTED from users;<BR>USERID PASSWORD DECRYPTED<BR>------ --------- ----------<BR>user1 user1234 user1234<BR>user2 abcd1234 abcd1234<BR>user3 oracle12 oracle12<o:p></o:p></P>
<P >大家可以看到,解密结果和密码原文完全一模一样,这说明我们的加密解密过程是正确的。<o:p></o:p></P>
<P ><B >5</B><B >、进一步思考</B><B ><o:p></o:p></B></P>
<P >我们再看一下表users:<o:p></o:p></P>
<P >create table users(<BR> userid varchar2(50) primary key,<BR> password varchar2(64), --密码原文<BR> encrypted varchar2(64) --加密后的密码<BR> );<o:p></o:p></P>
<P >还有我们插入的数据:<o:p></o:p></P>
<P >insert into users values ('user1','user1234',null);<BR>insert into users values ('user2','abcd1234',null);<BR>insert into users values ('user3','oracle12',null);<o:p></o:p></P>
<P >以及加密输出结果;<BR>[/code]<BR>USERID PASSWORD ENCRYPTED <BR>------ --------- ----------------<BR>user1 user1234 69EF<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="a">3A</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="211" UnitName="a">211A</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0F</st1:chmetcnv><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="2" UnitName="C">2C</st1:chmetcnv>32<BR>user2 abcd1234 CF<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7562203" UnitName="F">7562203F</st1:chmetcnv>6CEDE5<BR>user3 oracle12 65D71D7148FA001D<BR>[/code]<o:p></o:p></P>
<P >不知细心的朋友注意到没有?在表中,password 和 encrypted 的长度都是64,都是8的倍数,再看一下我们的密码原文和加密后的密码也是8的倍数,这不是巧合,而是DES算法和Triple DES算法的特征之一。输入长度必须是8的倍数,而输出也是8的倍数,所以我们的字段长度也是8的倍数。如果输入不是8的倍数会怎样?大家可以把密码原文修改一下试试。<o:p></o:p></P>
<P ><B>6</B><B>、</B><B> </B><B>密钥的保存</B><B> </B><B ><BR></B>不管我们用什么样的加密算法,有一点非常重要的是:密钥的保存。密钥就是一把钥匙,因为加密算法是公开的,所以你无论如何加密,只要我知道你的密钥,我就可以解密,那么你的加密就没有效果。在本文中,我们的密钥是这样定义的:<o:p></o:p></P>
<P >iKey varchar2(8):='oracle9i';<o:p></o:p></P>
<P >oracle9i就是我们的密钥。<BR>所以,如果只是简单地把以上程序在oracle上运行一下就使用,那么任何有权限登陆的人看到这个程序,就可以知道密钥。所以简单的做法是利用Oracle提供的WRAP把整个程序加密,用加密后的文本创建程序。这样别人就看不到你的源代码了。把程序保存为source.sql,在Dos命令下输入:<o:p></o:p></P>
<P >Wrap iname=source.sql oname=target.sql<o:p></o:p></P>
<P >就可以了,然后SQL Plus运行target.sql。<BR>当然了,这里讲的密钥保存还是很简单的。并不是百分百保险。大家可以自己想想如何更安全地保持你的密钥。<o:p></o:p></P> dddddddddddddddddddddddddddd
页:
[1]
