3

We have one requirement to mask a particular table column using a Oracle function which gives persistent masked output string.

  • We tried Oracle Hash Function but it does not give String type return value.
  • We tried Oracle Random function (dbms_random.string) but it does not give Persistent output string.

I read on internet that this is called deterministic masking. But we do not want to use Oracle Enterprise Manager; however we require a direct Oracle function.

Please suggest.

Hadi
  • 36,233
  • 13
  • 65
  • 124
Sam
  • 43
  • 2
  • 4
  • Don't think there is an inbuilt Oracle function for this. Believe you will need to create a package or pl/sql block for this to replace the sensitive info with the masked values. You can use the Regexp_Replace to replace the values based on the patterns. – vishad Mar 21 '14 at 07:09
  • Oracle provide a data masking pack however this is not free and requires additional licensing costs. Link to what the latest version can do: http://www.oracle.com/technetwork/database/manageability/ds-data-masking-12c-1964664.pdf – Ian Carpenter Mar 21 '14 at 07:49

4 Answers4

4

This problem is easily solved in 12c with the function STANDARD_HASH.

The solution in previous versions is only slightly more complicated. Build a simple wrapper around DBMS_CRYPTO that acts just like STANDARD_HASH:

--Imitation of the 12c function with the same name.
--Remember to drop this function when you upgrade!
create or replace function standard_hash(
    p_string varchar2,
    p_method varchar2 default 'SHA1'
) return varchar2 is
    v_method number;
    v_invalid_identifier exception;
    pragma exception_init(v_invalid_identifier, -904);
begin
    --Intentionally case-sensitive, just like the 12c version.
    if p_method = 'SHA1' then
        v_method := dbms_crypto.hash_sh1;
    --These algorithms are only available in 12c and above.
    $IF NOT DBMS_DB_VERSION.VER_LE_11 $THEN
        elsif p_method = 'SHA256' then
            v_method := dbms_crypto.hash_sh256;
        elsif p_method = 'SHA384' then
            v_method := dbms_crypto.hash_sh384;
        elsif p_method = 'SHA512' then
            v_method := dbms_crypto.hash_sh512;
    $END
    elsif p_method = 'MD5' then
        v_method := dbms_crypto.hash_md5;
    else
        raise v_invalid_identifier;
    end if;

    return rawToHex(dbms_crypto.hash(utl_raw.cast_to_raw(p_string), v_method));
end;
/

You may need to logon with SYS and grant your user access to DBMS_CRYPTO to make the function work:

grant execute on sys.dbms_crypto to <your_schema>;

Create a public synonym, grant it to everyone, and it works exactly the same way.

create public synonym standard_hash for <schema with function>.standard_hash;
grant execute on standard_hash to public;

select standard_hash('Some text', 'MD5') from dual;
    9DB5682A4D778CA2CB79580BDB67083F

select standard_hash('Some text', 'md5') from dual;
    ORA-00904: : invalid identifier

Here is a simple example of using the function:

update some_table
set column1 = standard_hash(column1),
    column2 = standard_hash(column2);

But updating large amounts of data can be slow. It may be faster to create a new table, drop the old one, rename the new one, etc. And the hash value may be larger than the column size, it may be necessary to alter table some_table modify column1 varchar2(40 byte);

It amazes me how many products and tools there are to do such a simple thing.

Jon Heller
  • 34,999
  • 6
  • 74
  • 132
  • +1 for working solution. but i want to ask how can we use that function to update a table? – AloneInTheDark Apr 15 '14 at 12:24
  • @AloneInTheDark I added some more information to the answer. – Jon Heller Apr 15 '14 at 17:33
  • @OliverStutz I just tried it with SHA512 and it works just like the official function. Although my original answer didn't include a step to grant access to the DBMS_CRYPTO package. That may have been causing problems so I added it to my answer. – Jon Heller Sep 17 '17 at 02:11
  • @JonHeller the Problem is that in 11g there are no hashes beyond SHA-1 in the package! – Oliver Sep 18 '17 at 16:03
  • @OliverStutz You're right, I didn't notice because I was only testing on 11g. I added PL/SQL conditional compilation so the more modern cryptographic functions are not included in 11g. I just tested it and it should work on 11g now, but only for MD5 and SHA1. – Jon Heller Sep 19 '17 at 18:39
  • @JonHeller thanks for your efforts, if anyone lands here with an Oracle 11g Crypto Issue they should consider using a function with Java code to retreive SHA-256 or SHA-512 hashes – Oliver Sep 20 '17 at 11:09
0

If you looking something like mask the production data to move it into non-prod for integration testing. Below the "user defined" function would be helpful to you. This function will work only 10G and above.

create or replace function scrubbing(word in varchar2)
return varchar2
as
each_var char(2);
final_val varchar2(100);
complete_data varchar2(4000);
each_word varchar2(1000);
cursor val is select substr(replace(word,' ','#'),-level,1)  from dual connect by level<=length(word);
begin
open val;
--final_val:= '';
loop
    fetch val into each_var;
    exit when val%NOTFOUND;
    --dbms_output.put_line(each_var);
    final_val := trim(final_val)||trim(each_var);
    --dbms_output.put_line(final_val);
    select regexp_substr(final_val,'[A-Za-z]+') into each_word from dual;
    select replace(translate(final_val,each_word,dbms_random.string('L',length(word))),'#',' ') into complete_data from dual;
end loop;
return complete_data;
end;    
  • There are a few problems with this function. It needlessly uses SQL, which will cause many context switches and poor performance. And it is not deterministic, the same input will not always produce the same output. And it probably has some cryptographic problems. – Jon Heller May 11 '16 at 01:44
  • Can you explain in details about many how it will "context switches and poor performance" as it is directly query in dual only. The main purpose of this function is not to create same output. – Vinoth Durairaj May 13 '16 at 06:25
  • 1
    There's overhead whenever PL/SQL calls SQL. The `select ... from dual;` can be replaced by a PL/SQL assignment statement, `variable := ...;`. – Jon Heller May 13 '16 at 15:21
0

In Oracle 12C dbms_redact.add_policy is available. It can be used to get the masked value in the select query itself.

dowonderatwill
  • 109
  • 1
  • 15
-1

You can use dbms_crpyto package of oracle , first you need to convert varchar2 type to raw then mask the data according to the hash value.