2009-11-17 134 views
14

我在Oracle數據庫的select中對某行做sha1哈希有問題。在Oracle中製作一行sha1哈希

SELECT *,HASHBYTES('SHA1',CAST(ID as varchar(10)+ 
    TextEntry1+TextEntry2+CAST(Timestamp as varchar(10)) as Hash 
FROM dbo.ExampleTable 
WHERE ID = [foo] 

不過,我似乎無法找到一個類似的功能與Oracle工作時使用的:我已經在MSSQL如下做到了。 至於我的谷歌搜索帶來了我,我猜dbms_crypto.hash_sh1與它有關,但我還沒有能夠包圍我的大腦呢...

任何指針會很大讚賞。

回答

23

DBMS_CRYPTO是生成哈希的正確包。默認情況下,它不會授予PUBLIC,您必須特別授予它(GRANT EXECUTE ON SYS.DBMS_CRYPTO TO user1)。

該函數的結果是數據類型RAW。您可以將其存儲在RAW列中,或使用RAWTOHEXUTL_ENCODE.BASE64_ENCODE函數將其轉換爲VARCHAR2

HASH函數被重載以接受三種數據類型作爲輸入:RAW,CLOBBLOB。由於rules of implicit conversion,如果您使用VARCHAR2作爲輸入,Oracle會嘗試將其轉換爲RAW,並且很可能會失敗,因爲此轉換僅適用於十六進制字符串。

如果使用VARCHAR2然後,你需要將輸入轉換爲二進制數據類型或CLOB,例如:

DECLARE 
    x RAW(20); 
BEGIN 
    SELECT sys.dbms_crypto.hash(utl_raw.cast_to_raw(col1||col2||to_char(col3)), 
           sys.dbms_crypto.hash_sh1) 
    INTO x 
    FROM t; 
END; 

你的DBMS_CRYPTO.hash

+2

感謝您的幫助。我必須使用值dbms_crypto.hash_sh1代表(整數3)而不是常量,以便在執行常規SQL時使其工作。 SELECT sys.dbms_crypto.hash(utl_raw.cast_to_raw(col1),3)FROM t; – PrometheusDrake 2009-11-18 08:01:48

+2

我不認爲這對於11g R2是完全正確的。 'dbms_crypto.hash'似乎有3個重載的'raw','blob'和'clob'版本。 'varchar2'值必須用'utl_i18n.string_to_raw'或'utl_raw.cast_to_raw'顯式轉換爲'raw'。或者使用'clobs'作爲角色數據。 – user272735 2015-01-12 12:53:58

+0

如果有一些列沒有字符串數據類型,該怎麼辦? – ca9163d9 2017-10-04 18:36:08

7

的DBMS_CRYPTO的文檔中找到更多的信息包不支持varchar2。它適用於原始類型,所以如果你需要一個varchar2你必須將其轉換。下面是一個示例函數,顯示如何執行此操作:

declare 
    p_string varchar2(2000) := 'Hello world !'; 
    lv_hash_value_md5 raw (100); 
    lv_hash_value_sh1 raw (100); 
    lv_varchar_key_md5 varchar2 (32); 
    lv_varchar_key_sh1 varchar2 (40); 
begin 
    lv_hash_value_md5 := 
    dbms_crypto.hash (src => utl_raw.cast_to_raw (p_string), 
         typ => dbms_crypto.hash_md5); 

    -- convert into varchar2 
    select lower (to_char (rawtohex (lv_hash_value_md5))) 
    into lv_varchar_key_md5 
    from dual; 

    lv_hash_value_sh1 := 
    dbms_crypto.hash (src => utl_raw.cast_to_raw (p_string), 
         typ => dbms_crypto.hash_sh1); 

    -- convert into varchar2 
    select lower (to_char (rawtohex (lv_hash_value_sh1))) 
    into lv_varchar_key_sh1 
    from dual; 

    -- 
    dbms_output.put_line('String to encrypt : '||p_string); 
    dbms_output.put_line('MD5 encryption : '||lv_varchar_key_md5); 
    dbms_output.put_line('SHA1 encryption : '||lv_varchar_key_sh1); 
end; 
3

您可以在您最喜歡的包中定義此函數,我在utils_pkg中定義了此函數。

FUNCTION SHA1(STRING_TO_ENCRIPT VARCHAR2) RETURN VARCHAR2 AS 
BEGIN 
RETURN LOWER(TO_CHAR(RAWTOHEX(SYS.DBMS_CRYPTO.HASH(UTL_RAW.CAST_TO_RAW(STRING_TO_ENCRIPT), SYS.DBMS_CRYPTO.HASH_SH1)))); 
END SHA1; 

我們稱之爲

SELECT UTILS_PKG.SHA1('My Text') AS SHA1 FROM DUAL; 

的響應是

SHA1 
-------------------------------------------- 
5411d08baddc1ad09fa3329f9920814c33ea10c0 

您可以從一些表中選擇一個列:

SELECT UTILS_PKG.SHA1(myTextColumn) FROM myTable; 

享受!