PBKDF2 in Oracle

Recently we were looking at password encryption and decided to implement PBKDF2 for lots of good reasons which I won’t repeat here. Unfortunately there is no native implementation for this in Oracle (as of, and a Google search turned up nothing useful.

My first thought was to write a call specification to make use of the implementation in Java that is installed in the database. This compiled fine, however when executed it transpired that the algorithm was introduced in Java 1.6, and the version in the database is Java 1.5.

So I needed to code the algorithm in PL/SQL. This wasn’t especially difficult, however I think it is worth publishing in case it saves time for anyone else.

Here is the function:

( p_password   IN VARCHAR2
, p_salt       IN VARCHAR2
, p_count      IN INTEGER
, p_key_length IN INTEGER
  l_block_count INTEGER;
  l_last        RAW(32767);
  l_xorsum      RAW(32767);
  l_result      RAW(32767);
  l_block_count := ceil(p_key_length / 20);  -- 20 bytes for SHA1.

  FOR i IN 1..l_block_count
    l_last := utl_raw.concat(utl_raw.cast_to_raw(p_salt), utl_raw.cast_from_binary_integer(i, utl_raw.big_endian));

    l_xorsum := NULL;

    FOR j IN 1..p_count
      l_last := dbms_crypto.mac(l_last, dbms_crypto.hmac_sh1, utl_raw.cast_to_raw(p_password));

      IF l_xorsum IS NULL
        l_xorsum := l_last;
        l_xorsum := utl_raw.bit_xor(l_xorsum, l_last);
      END IF;


    l_result := utl_raw.concat(l_result, l_xorsum);


  RETURN rawtohex(utl_raw.substr(l_result, 1, p_key_length));

END pbkdf2;

And here is an implementation of the test vectors from https://www.ietf.org/rfc/rfc6070.txt  Note this takes about 3 minutes to run (on my hardware), owing to the case with 16M iterations.

     , pbkdf2(password, salt, iterations, key_length) output
FROM   ( SELECT 'password' password
              , 'salt' salt
              , 1 iterations
              , 20 key_length
              , '0C60C80F961F0E71F3A9B524AF6012062FE037A6' expected_output
         FROM   DUAL
         UNION ALL
         SELECT 'password'
              , 'salt'
              , 2
              , 20
              , 'EA6C014DC72D6F8CCD1ED92ACE1D41F0D8DE8957'
         FROM   DUAL
         UNION ALL
         SELECT 'password'
              , 'salt'
              , 4096
              , 20
              , '4B007901B765489ABEAD49D926F721D065A429C1'
         FROM   DUAL
         UNION ALL
         SELECT 'password'
              , 'salt'
              , 16777216
              , 20
              , 'EEFE3D61CD4DA4E4E9945B3D6BA2158C2634E984'
         FROM   DUAL
         UNION ALL
         SELECT 'passwordPASSWORDpassword'
              , 'saltSALTsaltSALTsaltSALTsaltSALTsalt'
              , 4096
              , 25
              , '3D2EEC4FE41C849B80C8D83662C0E44A8B291A964CF2F07038'
         FROM   DUAL
         UNION ALL
         SELECT 'pass'||chr(0)||'word'
              , 'sa'||chr(0)||'lt'
              , 4096
              , 16
              , '56FA6AA75548099DCC37D7F03425E0C3'
         FROM   DUAL
       ) t

Platform Information

The material in this article was most recently tested against Oracle on 64-bit Linux.

This entry was posted in Security and tagged . Bookmark the permalink.

3 Responses to PBKDF2 in Oracle

  1. Yugene says:

    Thanks for this function! You’ve saved a lot of time for me 🙂


  2. Oscar says:

    Great, thanks .

    Is it possible to change from 20 bytes of SHA1 to 32 bytes of sha256?

    I’ve changed and throws me an error. Perhaps it is a misconception.



    • mikepargeter says:

      I think that should work. You would need to change the “20” in the assignment to “l_block_count” to “32”. Then in the call to “dbms_crypto.mac” change “dbms_crypto.hmac_sh1” to “dbms_crypto.hmac_sh256”.

      The only caveat is that (according to the documentation), dbms_crypto supports SHA256 from Oracle 12c onwards. So if you were trying in Oracle 11g then I would expect an error for the undefined constant “hmac_sh256”.

      If I get time I may extend the function to take the MAC function as a parameter.


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 )

Google+ photo

You are commenting using your Google+ 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