Question

Length of hash generated from standard_hash or dbms_crypto in oracle

I am using below method to generate a hash in oracle:

select STANDARD_HASH(x, 'SHA1'), length(STANDARD_HASH(x, 'SHA1')) from (
    select 'aa' x from dual union all
    select 'bb' x from dual union all
    select 'cc' x from dual
)

As you can see it always generates a RAW data with length as 40. enter image description here

I need a hash of length RAW(8) instead of RAW(40). Is there any readily available way to do it? If no, is there a way to generate a hash of length RAW(8) using DBMS_CRYPTO?

 3  42  3
1 Jan 1970

Solution

 0

The SHA-1 algorithm always generates a 160-bit (20-byte) hash; you cannot vary the size of it.

You are seeing 40 bytes because you are using LENGTH which expects the first argument to be a string and the RAW is being implicitly converted to a hexadecimal string with two hexadecimal characters per byte which doubles the length.

If you use UTL_RAW.LENGTH to generate the output then you will see the byte length without converting to a string.

If you only want an 8-bytes then you could use UTL_RAW.SUBSTR to take the first 8-bytes of the SHA-1 hash:

SELECT STANDARD_HASH(x, 'SHA1') AS hash,
       UTL_RAW.LENGTH(STANDARD_HASH(x, 'SHA1')) AS len,
       UTL_RAW.SUBSTR(STANDARD_HASH(x, 'SHA1'), 1, 8) AS byte8_hash,
       UTL_RAW.LENGTH(UTL_RAW.SUBSTR(STANDARD_HASH(x, 'SHA1'), 1, 8)) AS byte8_len
FROM   table_name

Which, for the sample data:

CREATE TABLE table_name (x) AS
  SELECT 'aa' x FROM DUAL UNION ALL
  SELECT 'bb' x FROM DUAL UNION ALL
  SELECT 'cc' x FROM DUAL

Outputs:

HASH LEN BYTE8_HASH BYTE8_LEN
0xE0C9035898DD52FC65C41454CEC9C4D2611BFB37 20 0xE0C9035898DD52FC 8
0x9A900F538965A426994E1E90600920AFF0B4E8D2 20 0x9A900F538965A426 8
0xBDB480DE655AA6EC75CA058C849C4FAF3C0F75B1 20 0xBDB480DE655AA6EC 8

(Note: The risk of hash-collisions will be greater with an 8-byte hash compared to a 20-byte hash but, assuming that the original hash function is sufficiently random, truncating a longer hash to 8-bytes should not increase the hash-collisions when compared to directly generating an 8-byte hash.)

fiddle

2024-07-03
MT0