DBMS_CRYPTO包對Oracle加密
?
?
??? 對Oracle內部數據的加密,可以簡單得使用DBMS_CRYPTO來進行,效果還是不錯的,而且使用也比較方便,所以今天專門來學習一下這個包的使用方法。在使用之前,要注意兩件事情:
?
??? 1、DBMS_CRYPTO包是10g才有的,如果在10g以前的版本,使用DBMS_OBFUSCATION_TOOLKIT包;
??? 2、DBMS_CRYPTO默認只有SYSDBA用戶才可執行,所以其他的任何用戶都需要SYSDBA進行賦權。
?
?
一、簡單的隨機值生成
?
??? 使用DBMS_CRYPTO包可以有3個函數來生成簡單的隨機值,包括3種——數字、整數、字符。使用這些隨機數生成函數是為了在加密是生成隨機的密匙。這幾個函數的使用很簡單,看一下具體例子就可以馬上明白:
SQL> select DBMS_CRYPTO.RandomInteger from dual;--生成整數(有正有負)
?
RANDOMINTEGER
-------------
?? -284171810
SQL> select DBMS_CRYPTO.RandomBytes(6) from dual;--生成6位Bytes(注意返回的不是byte是raw)
?
DBMS_CRYPTO.RANDOMBYTES(6)
------------------------------
FFEE2CB53DB4
SQL> select DBMS_CRYPTO.RandomNumber from dual;--生成Number(正數)
?
RANDOMNUMBER
------------
6.6453693840
?
?
二、簡單的示例
?
??? 首先看一下用于生成加密的函數(暫時不考慮BLOB類型的加密):
?
??? FUNCTION? Encrypt (src IN??????????? RAW,
?????????????????????? typ IN??????????? PLS_INTEGER,
?????????????????????? key IN??????????? RAW,
?????????????????????? iv? IN??????????? RAW????????? DEFAULT NULL)
????? RETURN RAW;
?
??? 解釋一下:
?
??? 1、src:需要加密的內容,但是需要轉換為RAW格式,不能直接對VARCHAR2格式加密
??? 2、typ:加密類型,由DBMS_CRYPTO定義,可以查詢DBMS_CRYPTO包中的Declare部分
??? 3、key:即加密的密匙,如需解密則需要知道原先的密匙
??? 4、iv:block密碼的選項,一般都置為默認,默認為null
?
??? 下面簡單舉例說明:
?
SQL> DECLARE
? 2??? input_string???? VARCHAR2(30) := '需要加密的內容';
? 3??? raw_input??????? RAW(128) := UTL_RAW.CAST_TO_RAW(input_string);
? 4??? --將需要加密的內容轉換成RAW格式
? 5??? raw_key????????? RAW(256);
? 6??? encrypted_raw??? RAW(2048);
? 7??? encrypted_string VARCHAR2(2048);
? 8??? decrypted_raw??? RAW(2048);
? 9??? decrypted_string VARCHAR2(2048);
10?
11? BEGIN
12??? dbms_output.put_line('> ========= Get Key Bytes =========');
13?
14??? raw_key := dbms_crypto.randombytes(24);
15??? --隨機生成的48位字符密匙
16??? dbms_output.put_line('> Key String length: ' || UTL_RAW.LENGTH(raw_key));
17??? dbms_output.put_line('> Key String: ' || UTL_RAW.CAST_TO_VARCHAR2(raw_key));
18??? dbms_output.put_line('> Input String: ' || input_string);
19??? dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');
20??? --加密
21??? encrypted_raw := dbms_crypto.Encrypt(src => raw_input,
22???????????????????????????????????????? typ => DBMS_CRYPTO.DES3_CBC_PKCS5,
23???????????????????????????????????????? key => raw_key);
24?
25??? dbms_output.put_line('> Encrypted hex value : ' || rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));
26??? dbms_output.put_line('> Encrypted varchar2 value: ' || UTL_RAW.CAST_TO_VARCHAR2(encrypted_raw));
27??? --解密
28??? decrypted_raw := dbms_crypto.Decrypt(src => encrypted_raw,
29???????????????????????????????????????? typ => DBMS_CRYPTO.DES3_CBC_PKCS5,
30???????????????????????????????????????? key => raw_key);
31??? --將解密后的RAW轉換成String
32??? decrypted_string := UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw);
33?
34??? dbms_output.put_line('> Decrypted string output : ' || decrypted_string);
35?
36??? if input_string = decrypted_string THEN
37????? dbms_output.put_line('> String DES Encyption and Decryption successful');
38??? END if;
39? END;
40? /
?
> ========= Get Key Bytes =========
> Key String length: 24
> Key String: 峈報T??崛╭顋賣I~漥?篻
> Input String: 需要加密的內容
> ========= BEGIN TEST Encrypt =========
> Encrypted hex value : 374132424133453633303945433530364534414334443943303346343735303643464630393330313436454441443930
> Encrypted varchar2 value: z+f0炁洮M?魎橡?F憝
???????????
?
??? 說明:
?
??? 1、可以看到,用dbms_crypto.randombytes(24)生成的是24位的亂碼
??? 2、解密時必須提供加密時的Key,所以在使用加密時可以使用固定的復雜字符串。
?
?
三、我設的加密/解密函數
?
SQL>
SQL> --加密函數
SQL> create or replace function t_to_password(string_in in varchar2) return raw is
? 2??? string_in_raw RAW(128) := UTL_RAW.CAST_TO_RAW(string_in);
? 3??? key_string varchar2(32) := 'WANGXIAOQI._ROW@KEY-PASSWORD8888';
? 4??? key_raw RAW(128) := UTL_RAW.CAST_TO_RAW(key_string);
? 5??? encrypted_raw RAW(128);
? 6? begin
? 7??? encrypted_raw := dbms_crypto.Encrypt(src => string_in_raw,
? 8???????????????????????????????????????? typ => DBMS_CRYPTO.DES3_CBC_PKCS5,
? 9???????????????????????????????????????? key => key_raw);
10??? return encrypted_raw;
11? end;
12? /
?
Function created
?
SQL>
SQL> --解密函數
SQL> create or replace function t_to_back(raw_in in raw) return varchar2 is
? 2??? string_out varchar2(50);
? 3??? key_string varchar2(32) := 'WANGXIAOQImailto:'SINATAY.COM_ROW@KEY-PASSWORD8888';
? 4??? key_raw RAW(128) := UTL_RAW.CAST_TO_RAW(key_string);
? 5??? decrypted_raw RAW(128);
? 6? begin
? 7??? decrypted_raw := dbms_crypto.Decrypt(src => raw_in,
? 8???????????????????????????????????????? typ => DBMS_CRYPTO.DES3_CBC_PKCS5,
? 9???????????????????????????????????????? key => key_raw);
10??? string_out := UTL_RAW.cast_to_varchar2(decrypted_raw);
11??? return string_out;
12? end;
13? /
?
Function created
?
SQL>
SQL> create table t_name(a int primary key,
? 2????????????????????? psw varchar2(100));
?
Table created
?
SQL>
SQL> insert into t_name values(1, t_to_password('password'));
?
1 row inserted
SQL> insert into t_name values(2, t_to_password('ilovebaby'));
?
1 row inserted
SQL> insert into t_name values(3, t_to_password('@1123'));
?
1 row inserted
?
SQL> select * from t_name;
?
????????????????????????????????????? A PSW
--------------------------------------- --------------------------------------------------------------------------------
????????????????????????????????????? 1 A8C933B456FEDE0E99D7A55CC99758E6
????????????????????????????????????? 2 D8DDDA409E4AB8E19144C0762027ACCB
????????????????????????????????????? 3 D7116CC53A09F98F
?
SQL> select a,t_to_back(psw) psw from t_name;
?
????????????????????????????????????? A PSW
--------------------------------------- --------------------------------------------------------------------------------
????????????????????????????????????? 1 password
????????????????????????????????????? 2 ilovebaby
????????????????????????????????????? 3 @1123
?
SQL>
?
?
??? OK,測試成功。
?
?
??? 如果需要了解詳細的DBMS_CRYPTO包使用方法,可以參閱官方文檔:
?