Klaus' Blog

going public

  • Categories

  • Archives

Oracle Obfuscated Sequences

Posted by klauskurz on 24. February 2010

Obfuscating Sequences

CREATE OR REPLACE PACKAGE obfuscate_seq IS

  FUNCTION obfuscate_seq(i_seq IN NUMBER) RETURN NUMBER;
  FUNCTION deobfuscate_seq(i_nextval IN NUMBER) RETURN NUMBER;

END obfuscate_seq;
/
CREATE OR REPLACE PACKAGE BODY obfuscate_seq IS

  g_crypto_mod NUMBER := dbms_crypto.des3_cbc_pkcs5;

  g_seq_key RAW(128) := hextoraw('082748387234987899239487972395030981208309823098');

  FUNCTION obfuscate_seq(i_seq IN NUMBER) RETURN NUMBER IS

    l_seed_raw    RAW(7); -- max 7 byte
    l_nextval     NUMBER(19); -- can hold 64bit signed integer
    l_nextval_raw RAW(8); -- max 8 byte
    l_salt        NUMBER(19);

  BEGIN
    -- max      = 2^56 = 2^(7*8) = 72057594037927936 = 0xFFFFFFFFFFFFFF
    -- max seq  = 2^32 = 2^(4*8) = 4294967296        =       0xFFFFFFFF
    -- max salt = 2^24 = 2^(3*8) = 16777216          = 0xFFFFFF

    l_salt := trunc(dbms_random.VALUE(1,
                                      16777216 + 1));

    l_seed_raw := to_char(l_salt,
                          'FM00000X') || to_char(i_seq,
                                                 'FM0000000X');

    dbms_output.put_line('   seed:   0x' || l_seed_raw || ' len: ' || utl_raw.length(l_seed_raw) || ' decimal: ' ||
                         to_number(l_seed_raw,
                                   'XXXXXXXXXXXXXX'));

    l_nextval_raw := dbms_crypto.encrypt(l_seed_raw,
                                         g_crypto_mod,
                                         g_seq_key);

    IF (to_number(substr(l_nextval_raw,
                         1,
                         1),
                  'X') > 7)
    THEN
      l_nextval := to_number(l_nextval_raw,
                             'XXXXXXXXXXXXXXXX') - 18446744073709551616; --  number - 2^64 (2 complement)
    ELSE
      l_nextval := to_number(l_nextval_raw,
                             'XXXXXXXXXXXXXXXX');
    END IF;

    dbms_output.put_line('nextval: 0x' || l_nextval_raw || ' len: ' || utl_raw.length(l_nextval_raw) || ' decimal: ' ||
                         l_nextval);

    RETURN l_nextval;

  END;

  FUNCTION deobfuscate_seq(i_nextval IN NUMBER) RETURN NUMBER IS

    l_nextval_raw RAW(8); -- max 8 byte
    l_seed_raw    RAW(7); -- max 7 byte
    l_seq         NUMBER(10); -- max 4 byte

  BEGIN

    IF (i_nextval < 0)
    THEN

      l_nextval_raw := to_char(i_nextval + 18446744073709551616,
                               'FM000000000000000X');

    ELSE
      l_nextval_raw := to_char(i_nextval,
                               'FM000000000000000X');
    END IF;

    dbms_output.put_line('nextval: 0x' || l_nextval_raw || ' len: ' || utl_raw.length(l_nextval_raw) || ' decimal: ' ||
                         i_nextval);

    l_seed_raw := dbms_crypto.decrypt(l_nextval_raw,
                                      g_crypto_mod,
                                      g_seq_key);

    dbms_output.put_line('   seed:   0x' || l_seed_raw || ' len: ' || utl_raw.length(l_seed_raw) || ' decimal: ' ||
                         to_number(l_seed_raw,
                                   'XXXXXXXXXXXXXX'));

    l_seq := to_number(substr(to_char(l_seed_raw),
                              7),
                       'XXXXXXXXXXXXXX');

    RETURN l_seq;
  END;

END obfuscate_seq;
/

Test Script

DECLARE
  seq_original   NUMBER(10);
  seq_obfuscated NUMBER;
  seq_restored   NUMBER;
BEGIN
  seq_original   := 1;
  seq_obfuscated := obfuscate_seq.obfuscate_seq(seq_original);
  seq_restored   := obfuscate_seq.deobfuscate_seq(seq_obfuscated);
  dbms_output.put_line('seq_original : ' || seq_original);
  dbms_output.put_line('seq_restored : ' || seq_restored);

  seq_original   := 4294967295;
  seq_obfuscated := obfuscate_seq.obfuscate_seq(seq_original);
  seq_restored   := obfuscate_seq.deobfuscate_seq(seq_obfuscated);
  dbms_output.put_line('seq_original : ' || seq_original);
  dbms_output.put_line('seq_restored : ' || seq_restored);

  seq_original   := 0;
  seq_obfuscated := obfuscate_seq.obfuscate_seq(seq_original);
  seq_restored   := obfuscate_seq.deobfuscate_seq(seq_obfuscated);
  dbms_output.put_line('seq_original : ' || seq_original);
  dbms_output.put_line('seq_restored : ' || seq_restored);
END;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: