Getting Oracle's MD5 to match PHP's MD5
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?
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.