2009-11-17 64 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; 

享受!