English 中文(简体)
Making a sha1-hash of a row in Oracle
原标题:

I m having a problem with making a sha1-hash of a row in a select on an Oracle database. I ve done it in MSSQL as follows:

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

However, I can t seem to find a similar function to use when working with Oracle. As far as my googling has brought me, I m guessing dbms_crypto.hash_sh1 has something to do with it, but I haven t been able to wrap my brain around it yet...

Any pointers would be greatly appreciated.

最佳回答

The package DBMS_CRYPTO is the correct package to generate hashes. It is not granted to PUBLIC by default, you will have to grant it specifically (GRANT EXECUTE ON SYS.DBMS_CRYPTO TO user1).

The result of this function is of datatype RAW. You can store it in a RAW column or convert it to VARCHAR2 using the RAWTOHEX or UTL_ENCODE.BASE64_ENCODE functions.

The HASH function is overloaded to accept three datatypes as input: RAW, CLOB and BLOB. Due to the rules of implicit conversion, if you use a VARCHAR2 as input, Oracle will try to convert it to RAW and will most likely fail since this conversion only works with hexadecimal strings.

If you use VARCHAR2 then, you need to convert the input to a binary datatype or a CLOB, for instance :

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;

you will find additional information in the documentation of DBMS_CRYPTO.hash

问题回答

The DBMS_crypto package does not support varchar2. It works with raw type so if you need a varchar2 you have to convert it. Here is a sample function showing how to do this :

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;

Just to put it here, if someone will search for.

In Oracle 12 you can use standard_hash(<your_value>, <algorythm>) function. With no parameter <algorythm> defined, it will generate SHA-1 hash (output datatype raw(20))

You can define this function in your favorite package, I defined in 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;

Now to call it

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

The response is

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

You can select a column from some table:

SELECT UTILS_PKG.SHA1(myTextColumn) FROM myTable;

Enjoy!

Oracle 19c:

select LOWER(standard_hash( 1234 )) from dual;

which is equivalent to

select LOWER(standard_hash( 1234 , SHA1 )) from dual;

will return an SHA1 hash.

For alternative algorithms see: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/STANDARD_HASH.html





相关问题
Export tables from SQL Server to be imported to Oracle 10g

I m trying to export some tables from SQL Server 2005 and then create those tables and populate them in Oracle. I have about 10 tables, varying from 4 columns up to 25. I m not using any constraints/...

Connecting to Oracle 10g with ODBC from Excel VBA

The following code works. the connection opens fine but recordset.recordCount always returns -1 when there is data in the table. ANd If I try to call any methods/properties on recordset it crashes ...

How to make a one to one left outer join?

I was wondering, is there a way to make a kind of one to one left outer join: I need a join that matches say table A with table B, for each record on table A it must search for its pair on table B, ...

Insert if not exists Oracle

I need to be able to run an Oracle query which goes to insert a number of rows, but it also checks to see if a primary key exists and if it does, then it skips that insert. Something like: INSERT ALL ...

How can I store NULLs in NOT NULL field?

I just came across NULL values in NOT-NULL fields in our test database. How could they get there? I know that NOT-NULL constraints can be altered with NOVALIDATE clause, but that would change table s ...

Type reference scope

I m studying databases and am currently working on a object-relational DB project and I ve encountered a small problem with the number of possible constraints in an object table. I m using "Database ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

热门标签