Question

I'm trying to compare an MD5 checksum generated by PHP to one generated by Oracle 10g. However it seems I'm comparing apples to oranges.

Here's what I did to test the comparison:

//md5 tests

  //php md5
  print md5('testingthemd5function');

  print '<br/><br/>';

  //oracle md5
  $md5query = "select md5hash('testingthemd5function') from dual";

  $stid = oci_parse($conn, $md5query);
  if (!$stid) {
   $e = oci_error($conn);
   print htmlentities($e['message']);
   exit;
  }

  $r = oci_execute($stid, OCI_DEFAULT);
  if (!$r) {
   $e = oci_error($stid);
   echo htmlentities($e['message']);
   exit;
  }

  $row = oci_fetch_row($stid); 
  print $row[0];

The md5 function (seen in the query above) in Oracle uses the 'dbms_obfuscation_toolkit.md5' package(?) and is defined like this:

CREATE OR REPLACE FUNCTION PORTAL.md5hash (v_input_string in varchar2) return varchar2     
is
   v_checksum varchar2(20);
   begin
   v_checksum := dbms_obfuscation_toolkit.md5 (input_string => v_input_string);
   return v_checksum;
end;

What comes out on my PHP page is:

29dbb90ea99a397b946518c84f45e016

)Û¹©š9{”eÈOEà 

Can anyone help me in getting the two to match?

Was it helpful?

Solution

It returns raw bytes, you need to convert that into hex.

$x = unpack("H*", $row[0]); 
echo $x[1];

OTHER TIPS

It appears that what's being printed from the Oracle query is the raw bytestream of the md5 checksum, mangled because most of those octets won't be ascii characters. Try converting it to hexadecimal first.

Create a function like the following:

create or replace
function md5( input varchar2 ) return sys.dbms_obfuscation_toolkit.varchar2_checksum as
begin
    return lower(rawtohex(utl_raw.cast_to_raw(sys.dbms_obfuscation_toolkit.md5( input_string => input ))));
end;

and call it like this:

select md5('foobar') from dual;

it seems that "dbms_obfuscation_toolkit.md5" does not really return in raw format, hence the need to call "utl_raw.cast_to_raw". I could be wrong though, there should be a better explanation for this.

In case you would want to have the md5 in Oracle, you can use this method:

select lower(rawtohex(md5hash('foobar'))) from dual

I got the same "numeric or value error" and found that two functions together work:

CREATE OR REPLACE FUNCTION MD5RAW( v_input_string in varchar2 )
RETURN varchar2 IS
v_checksum varchar2( 32 );
BEGIN
    v_checksum := SYS.DBMS_OBFUSCATION_TOOLKIT.MD5( input_string => v_input_string );
    return v_checksum;
END;

CREATE OR REPLACE FUNCTION MD5HEX( v_input_string in varchar2 )
RETURN varchar2 IS
v_hex_value varchar2( 32 );
BEGIN
    SELECT  LOWER( RAWTOHEX( MD5RAW( v_input_string ) ) ) 
    INTO    v_hex_value
    FROM    dual;
    return v_hex_value;
END;

Then you can run this query to get your checksum:

SELECT md5hex( 'my string smoked your hash' ) FROM dual;

That second function does the same thing as issuing the SELECT statement provided by Bazz on the function you provide, but I prefer to not have to do the rawToHex --> lower conversion inside of every query. That leaves too many things to potentially go wrong every time you use the query. I think it may be faster too since it is compiled at creation time instead of at runtime, but I may be wrong about that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top