I am trying to match a md5 has (generated through php) to its original value in a SQLExpress database.
I am using the following function in my SQL query
master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', 'ID'), 1, 0)
Where 'ID' is the field in the database.
However they both seem to return different values for the md5 hash. I have been using '12290' as a static value to test this.
php md5() returns: 0bd81786a8ec6ae9b22cbb3cb4d88179
The following SQL Statement returns the same output:
DECLARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', '12290'), 1, 0)
SELECT #password
Yet when I run the following statement from the table:
SELECT ID, master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(255), ID)), 1, 0) AS temp
FROM Clients
ORDER BY ID ASC
The 'temp' value matching to the 'ID' value of 12290 returns: 1867dce5f1ee1ddb46ff0ccd1fc58e03
Any help on the matter would be much appreciated!
Thanks
Python helped me to help you.
>>> from hashlib import md5
>>> md5('1\x002\x002\x009\x000\x00').digest().encode('hex')
'1867dce5f1ee1ddb46ff0ccd1fc58e03'
NVARCHAR is Unicode type and it seems from the above experiment that '12990' is stored as UTF-16LE in your database: '1\02\09\09\00\0'.
Assuming that the data encoding in the PHP is UTF-8 data and you don't want to change the existing data in the database, this is how you can fix your PHP script:
<?php
$password = '12290';
$hash = md5(mb_convert_encoding($password, 'UTF-16LE', 'UTF-8')) . "\n";
echo $hash;
?>
Output:
susam#swift:~$ php utf16le-hash.php
1867dce5f1ee1ddb46ff0ccd1fc58e03
In case the data in PHP is in some other encoding such as ASCII, ISO-8859-1, etc. you can change the third argument to mb_convert_encoding accordingly. The list of all supported encodings is available at: http://www.php.net/manual/en/mbstring.supported-encodings.php
Also, see http://www.php.net/manual/en/function.mb-convert-encoding.php
I don't have SQL server to test this on, but the CONVERT command might be creating the NVARCHAR with 240-odd trailing blanks (as you have specified NVARCHAR(255))
Try setting the NVARCHAR to the length of the ID to test:
ARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(5), '12290')), 1, 0)
SELECT #password
Try with different lengths in the CONVERT - is there any difference?
One of two things is most likely the problem:
Either the ID column in that row has a value not exactly equal to '12290' (e.g. extra whitespace)
Or the CONVERT function produces such a value
In any case, a standard debugging approach would be to use an SQL query to SELECT the string lengths of that ID field and the return value of CONVERT; if either is not equal to 5, you found the error.
Alternatively you can perform a dump of the table in question including data, and look at the generated INSERT statement to see what the database says the value in that column is.
Related
I have a table for things properties.
Such as id, amount, owner, attributes.
The attributes is stores as blob, and could be any small information about the thing itself,.
Like, the thing may have text on it, or it may has something about it that makes it more unique.
When you export a table/row in PhpMyAdmin, I get these really nice values
INSERT INTO `user_things` (`owner_id`, `id`, `thingId`, `count`, `attributes`) VALUES
(1, 6, 101, 1, 0x10c8431200);
And what I'm trying to do, is being able get information from the blob in PHP that displays the blob the same way PhpMyAdmin displayed it, so I can with PHP build a string of query there the blob value stays at a 0x00000 value.
I've tried to use this code: (mysqlQuery is a simplified function I created for mysqli queries, and that one works perfect so don't worry about that part)
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
but it doesn't work very well, and I've tried base64_encode and that doesn't give me the 0x000 either.
I would highly appreciate any help on this, how I can get the blob to the same type of value that PhpMyAdmin displays it as.
0x is just a convention for expressing hexadecimal values.
The 0x10c8431200 hexadecimal value is the same like 72079315456 decimal value.
You can try to convert binary data to hex with the bin2hex function.
Example:
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
echo bin2hex($blog);
I am trying to save a string in binary to save space in my MySQL DB. However, I am unable to retrieve the binary data correctly, so what am I doing wrong?
I have a database like:
CREATE TABLE `Test` (
ID INT NOT,
Value BLOB
);
I insert the data with statements like:
INSERT INTO `Test` (ID, Value) VALUES(1, b'10000001');
However, I can't retrieve the binary string when I select the value from the inserted row with the underneath query:
SELECT * FROM `Test`; //NOT WORKING. Returns Value=0
SELECT ID, BIN(Value) FROM `Test`; //NOT WORKING. Returns Value=0
What should I use? I have already tried using BIN(Value) in my query as shown above, but without any success. Thanks in advance.
Starting with a literal string of ones and zeroes is incredibly odd, but:
$ones_and_zeroes = '10000001';
// If you have a literal string of ones and zeroes that you need to convert
// to an actual number there's base_convert()
$hex_string = base_convert($ones_and_zeroes, 2, 16);
// $hex_string is now "81"
// you can convert this to an *actual* binary string with hex2bin()
$bin = hex2bin($hex_string);
// $bin now contains the byte 0x81
// now if you want to do it right:
$dbh = new PDO( ... );
$stmt = $dbh->prepare('INSERT INTO `Test` (ID, Value) VALUES(1, :bin)');
$stmt->execute(['bin'=>$bin]);
// or whatever the gross mysqli equivalent is.
I'm not going to show you how to do it wrong in PHP, but of you wanted to hand-write this query it would be:
INSERT INTO `Test` (ID, Value) VALUES(1, 0x81);
Hex-encoded data prefixed with '0x' being the only safe way [that I am aware of] to embed binary data in a text query, though it is EMINENTLY preferable to use prepared statements whenever possible as hex-encoding data like this doubles the length.
The best advice is to check if the insert query ran successfully i.e. with expected data inserted into DB using any MySQL admin tool.
Only then can you isolate whether the problem is with the retrieval or the insets itself
I have some very odd situation. I am making a query to a firebird database and there is mismatch with the result in PHP. In DB the result is just fine, but when it comes to PHP there are different values.
The query:
SELECT LIST(t."ID", ',') ID,t."Date", LIST(n."Name",',') Name
FROM "Tests" t
LEFT JOIN "Names of tests" n ON t."Name ID" = n."ID"
WHERE t."Locked" = 0
GROUP BY t."Date"
ORDER BY t."Date" DESC
Result in DB:
ID = 546,552 Date = 23.10.2015 Name = Математика (тест),География(тест)
Result in PHP:
ID => 0x0000000200000000,
Date => 2015-10-23,
Name => 0x0000000500000000
I am using "UTF-8" encoding when connecting to DB with ibase_connect() the database encoding is WIN1251.
The result type of LIST() is a blob, not a CHAR or VARCHAR. I don't use PHP myself, but I believe that the Firebird/Interbase driver for PHP requires you to explicitly request the blob.
The values you see for ID and Name are the blob ids that can be used to request the blobs.
You have two options:
Request the blob value using these blob ids, see ibase_blob_open and ibase_blob_get (afaik, you will need to do the correct byte to character conversion yourself)
Cast the value to a VARCHAR (eg CAST(LIST(t."ID", ',') AS VARCHAR(2048)) AS ID)
The downside of the second option is that if you can have really long results, then you also need to cast to a long VARCHAR, otherwise you get truncation errors; and unfortunately varchars are restricted to 32K-2 bytes (8191 characters for UTF8), and a row as a whole to 64K bytes.
I got a problem with SQL Server. My Task is it to realize a simple SQL Serverbased usersystem with PHP. The databases are also used by a MMORPG so I am not allowed to change the database structure or hashing alogrithms. The real cause of my problem is, that the password is hashed by the following alogrithm
HashBytes('MD5', REVERSE(UPPER(#ID)) + #PW)
I created a test user called test123 and pw hallo123 what conforms the password hash "0x7CEE495091E11FF9560D3D01651333220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
up to this point everything should be clear. Well but when I try to fetch the data by a query I get no results. I ran this query:
mssql_query("SELECT * FROM [DB_Member].[dbo].[Member] WHERE ID = 'test123' AND PW = HashBytes('MD5', REVERSE(UPPER('test123')) + 'hallo123')");
Which returns no result. But if I directly run this query
mssql_query("SELECT * FROM [DB_Member].[dbo].[Member] WHERE ID = 'test123' AND PW = 0x7CEE495091E11FF9560D3D01651333220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
I get the data without any problems
I'm grappling with this now for about eight hours but I can't figure out the problem.
I think you need to have a closer look at your data types. My guess is that the variables #ID and #PW is a char data type where the hash is generated. When you try the query, inserting 'test123' and 'hallo123', you need to add spaces after so they match whatever char(?) data type they were in the routine that created the hash.
Here is an example illustrating the difference in using char and varchar data types.
Using char
declare #PW char(25)
declare #ID char(25)
set #PW = 'hallo123'
set #ID = 'test123'
select (HashBytes('MD5', REVERSE(UPPER(#ID)) + #PW))
Hash result
0x9F1E0132F198216841E2608901D27115
Using varchar
declare #PW varchar(25)
declare #ID varchar(25)
set #PW = 'hallo123'
set #ID = 'test123'
select (HashBytes('MD5', REVERSE(UPPER(#ID)) + #PW))
Hash result
0x870B01D196916AFA88EBC900BE5395BE
The hashes clearly does not match.
The reason you have a bunch of zeros after your hash is because the hash is stored in a binary(60) field. HashBytes returns a VarBinary but that is not the reason for the query to fail. SQL Server does some kind of conversion when comparing binary with VarBinary.
Is it possible that whatever language you're using is encoding it strangely? What if you pull up a SQL profiler and look at the query that's being sent to see if you can spot the differences?
When I run SELECT HashBytes('MD5', REVERSE(UPPER('test123')) + 'hallo123'), I get the result 0x870B01D196916AFA88EBC900BE5395BE. Are you sure your hash creation is correct, and that you used the correct ID and password when creating the test user?
I am using mysql_fetch_assoc($query), one of the bit field returns out to be , which is supposedly to be true.
The problem is that I also need to output this to xml and it's an illegal xml character.
the charset for the db table is utf-8. why does this happen?
MySQL is literally returning 0x00 and 0x01 for the bit fields. You'll have to convert them into something appropriate either PHP-side
$bitvalue = ($bitvalue == 0x01) ? 'TRUE' : 'FALSE'
or in the query:
SELECT CAST(bitfield AS unsigned int)
FROM ...
which will convert it to an int and return as '0' and '1' (0x48 and 0x49).
Just as an aside, some of the older mysql libraries pre-date support for real bit fields in MySQL (when they were silently converted to char(1)) and will trash the values, so if you're stuck with one of those dinosaur versions, you may have to use the query version rather than the PHP-side conversion.
You can also use: ord($bitvalue).
Use the BIN function in your SELECT.
http://dev.mysql.com/doc/refman/5.0/en/bit-field-literals.html