ORACLE 字段AES算法加密、解密函数索引

--我这里使用的是utl_i18n.string_to_raw进行数据类型的转换,这是因为encrypt函数不但需要raw型数据,而且还需要使用专门的字符集—AL32UTF8,这里如果使用utl_raw.cast_to_raw,则会出现“ORA-06512”错误。
--只需要对解密函数写deterministic确定性函数
grant execute on SYS.DBMS_CRYPTO to enc;

create or replace function enc.encrypt(v_string in varchar2) return varchar2 is
encrypted_raw RAW (2000);
encryption_type PLS_INTEGER := SYS.DBMS_CRYPTO.ENCRYPT_DES + SYS.DBMS_CRYPTO.CHAIN_CBC + SYS.DBMS_CRYPTO.PAD_PKCS5;
v_key raw(128) := utl_i18n.string_to_raw( 'artos0011', 'AL32UTF8' );
begin
encrypted_raw := DBMS_CRYPTO.ENCRYPT
(
src => UTL_I18N.STRING_TO_RAW (v_string,'AL32UTF8'),
typ => encryption_type,
key => v_key
);
return RAWTOHEX(encrypted_raw);
end encrypt;
/

create or replace function enc.decrypt(v_str in varchar2) return varchar2 is
decrypted_raw raw(2000);
encryption_type PLS_INTEGER := SYS.DBMS_CRYPTO.ENCRYPT_DES + SYS.DBMS_CRYPTO.CHAIN_CBC + SYS.DBMS_CRYPTO.PAD_PKCS5;
v_key raw(128) := utl_i18n.string_to_raw( 'artos001', 'AL32UTF8' );
begin
decrypted_raw := DBMS_CRYPTO.Decrypt
(
src => HEXTORAW(v_str),
typ => encryption_type,
key => v_key
);
return UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
end decrypt;
/

select enc.encrypt('67634572') from dual;
select enc.decrypt(enc.encrypt('67634572')) from dual;

------------------------------------------------------------------------------------------------------------------------------------
--函数索引,对自定义解密函数
CREATE TABLE ENC.A34(ID NUMBER PRIMARY KEY,NAME VARCHAR2(200),ADDR VARCHAR2(200));

BEGIN
FOR I IN 1..10000 LOOP
INSERT INTO ENC.A34 SELECT I,'N'||I,'A'||I FROM DUAL;
END LOOP;
COMMIT;
END;
/

ALTER TABLE ENC.A34 ADD NAME_ VARCHAR2(4000);
CREATE VIEW ENC.V_A34 AS SELECT ID,ENC.DECRYPT(NAME_) AS NAME,ADDR FROM ENC.A34;
UPDATE ENC.A34 T SET T.NAME_=ENC.ENCRYPT(NAME);
COMMIT;

CREATE INDEX ENC.IDX_NAME_ ON ENC.A34(ENC.DECRYPT(NAME_));
--收集表统计信息
call dbms_stats.gather_table_stats(ownname => 'ENC',tabname => '"A34"',estimate_percent => 10,method_opt=> 'for all indexed columns');
call dbms_stats.gather_table_stats(ownname => 'ENC',tabname => '"A34"',CASCADE=>TRUE);

SELECT T.*,ENC.DECRYPT(T.NAME_) FROM ENC.A34 T WHERE T.ID='4';
SELECT /*+index(t IDX_NAME_)*/* FROM ENC.A34 T WHERE ENC.DECRYPT(NAME_)>='N4';
SELECT /*+index(t IDX_NAME_)*/* FROM ENC.A34 T WHERE ENC.DECRYPT(NAME_) = 'N44';
SELECT * FROM ENC.V_A34 T WHERE T.NAME='N44';
UPDATE ENC.A34 T SET T.NAME_=ENC.ENCRYPT(T.NAME||'4') WHERE T.ID=4;

--查看执行计划
EXPLAIN PLAN FOR SELECT * FROM ENC.A34 T WHERE T.NAME='N2';
SELECT * FROM table(DBMS_XPLAN.DISPLAY);

--SYS.DBMS_CRYPTO.ENCRYPT_DES为包变量,不能在sql中调用
SELECT SYS.DBMS_CRYPTO.ENCRYPT_DES + SYS.DBMS_CRYPTO.CHAIN_CBC + SYS.DBMS_CRYPTO.PAD_PKCS5 FROM DUAL;

------------------------------------------------------------------------------------------------------------------------------------
ORACLE 字段AES算法加密、解密(解决中文乱码问题)
1.加解密函数入口

CREATE OR REPLACE FUNCTION F_ZNMH_SMK_CRYPT(P_SRC IN VARCHAR2,
P_TYPE IN NUMBER)
RETURN VARCHAR2 IS
RESULT VARCHAR2(4000);

BEGIN
/*************************************************
信息加密函数 F_ZNMH_SMK_CRYPT 
入参:
P_SRC 输入明文字符串
P_TYPE 处理类型,1,为加密;2,为解密;
返回值:
RESULT 返回密文字符串,约定返回为 16进制密文字符串
 异常处理:
此函数不对任何异常做捕捉处理,请相应的程序模块对异常做捕捉处理。

加密方式:
密钥位数:AES192 DBMS_CRYPTO.ENCRYPT_AES192
连接方式:CBC DBMS_CRYPTO.CHAIN_CBC
填充方式:PKCS5 DBMS_CRYPTO.PAD_PKCS5
默认密钥:
KEY ZNMH1234
**************************************************/
DECLARE
KEY VARCHAR2(20);

BEGIN
KEY := 'ZNMH1234';
RESULT := 'ERROR ENCRPT INFO';

--P_TYPE为1时,代表加密;2时,代表解密;
IF (P_TYPE = 1) THEN
RESULT := ENCRYPT_FUNCTION(P_SRC, KEY);
ELSIF (P_TYPE = 2) THEN
RESULT := DECRYPT_FUNCTION(P_SRC, KEY);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE : ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM : ' || SQLERRM);
RETURN(RESULT);
END;
RETURN(RESULT);
END F_ZNMH_SMK_CRYPT;

2.加密函数

CREATE OR REPLACE FUNCTION ENCRYPT_FUNCTION(
V_STR VARCHAR2, V_KEY VARCHAR2) RETURN VARCHAR2 AS V_KEY_RAW RAW(24);
V_STR_RAW RAW(2000);
V_RETURN_STR VARCHAR2(2000);
V_TYPE PLS_INTEGER;
BEGIN
/*************************************************
加密函数 FUN_ENCRYPTION 
入参:
V_STR 输入明文字符串
V_KEY 输入密钥字符串,长度为24字节
返回值:
V_RETURN_STR 返回密文字符串,约定返回为 16进制密文字符串
 异常处理:
此函数不对任何异常做捕捉处理,请相应的程序模块对异常做捕捉处理。

加密方式:
密钥位数:AES192 DBMS_CRYPTO.ENCRYPT_AES192
连接方式:CBC DBMS_CRYPTO.CHAIN_CBC
填充方式:PKCS5 DBMS_CRYPTO.PAD_PKCS5

**************************************************/
V_KEY_RAW := UTL_I18N.STRING_TO_RAW(V_KEY, 'ZHS16GBK');
V_STR_RAW := UTL_I18N.STRING_TO_RAW(V_STR, 'ZHS16GBK');
-- 指定‘密钥算法’、‘工作模式’、‘填充方式’
V_TYPE := DBMS_CRYPTO.ENCRYPT_DES + DBMS_CRYPTO.CHAIN_ECB +
DBMS_CRYPTO.PAD_PKCS5;
V_STR_RAW := DBMS_CRYPTO.ENCRYPT(SRC => V_STR_RAW,
TYP => V_TYPE,
KEY => V_KEY_RAW);
V_RETURN_STR := RAWTOHEX(V_STR_RAW);
RETURN V_RETURN_STR;

/* EXCEPTION
WHEN OTHERS THEN
RETURN SQLERRM||SQLCODE ; */
END;


3.解密函数

CREATE OR REPLACE FUNCTION DECRYPT_FUNCTION(V_STR VARCHAR2, V_KEY VARCHAR2)
RETURN VARCHAR2 AS
V_KEY_RAW RAW(24);
V_STR_RAW RAW(2000);
V_RETURN_STR VARCHAR2(2000);
V_TYPE PLS_INTEGER;

BEGIN
/************************************************
解密函数 FUN_DECRYPTION 
入参:
V_STR 输入密文字符串,约定密文为16进制字符串
V_KEY 输入密钥字符串,长度为24字节
返回值:
V_RETURN_STR 返回明文字符串
异常处理:
此函数不对任何异常做捕捉处理,请相应的程序模块对异常做捕捉处理。

加密方式:
密钥位数:AES192 DBMS_CRYPTO.ENCRYPT_AES192
连接方式:CBC DBMS_CRYPTO.CHAIN_CBC
填充方式:PKCS5 DBMS_CRYPTO.PAD_PKCS5

***************************************************/
V_KEY_RAW := UTL_I18N.STRING_TO_RAW(V_KEY, 'ZHS16GBK');
V_STR_RAW := HEXTORAW(V_STR);
-- 指定‘密钥算法’、‘工作模式’、‘填充方式’
V_TYPE := DBMS_CRYPTO.ENCRYPT_DES + DBMS_CRYPTO.CHAIN_ECB +
DBMS_CRYPTO.PAD_PKCS5;
V_STR_RAW := DBMS_CRYPTO.DECRYPT(SRC => V_STR_RAW,
TYP => V_TYPE,
KEY => V_KEY_RAW);
V_RETURN_STR := UTL_I18N.RAW_TO_CHAR(V_STR_RAW, 'ZHS16GBK');
RETURN V_RETURN_STR;
/* EXCEPTION
WHEN OTHERS THEN
RETURN SQLERRM||SQLCODE ; */
END;

 

posted @ 2019-01-02 16:41  virtual_daemon  阅读(2897)  评论(0编辑  收藏  举报