Hashing Axapta 3 compatible passwords from PHP
As an interlude from the CoughPHP, I present the following:
The downside of working with legacy systems is that sometimes you find it necessary to work with existing data in ways that are completely arbitrary. The worst of all of these is password hashing.
It is often the case that you have to maintain compatibility with legacy passwords, and while you can replace the old algorithms going forward with a sensible schema, you still have to be able to validate against passwords stored in the old way.
So I present to you a way to hash passwords compatible with Axapta 3:
#!/usr/bin/php <?php echo "PHP_INT_SIZE: " . PHP_INT_SIZE . "\n"; function str2int($string) { $string = strtolower($string); $tmpCode = "0x015A4E35"; for ($i = 0; $i < strlen($string); $i++) { $tmpChar = gmp_and(gmp_init(ord($string[$i])), "0xff"); $tmpCode = gmp_and($tmpCode, "0xFFFFFFFF"); $tmpCode = gmp_add(gmp_and(gmp_mul($tmpCode, "8192"), "0x0FFFFE000"), gmp_and(gmp_div_q($tmpCode, "524288"), "0x000001FFF")); $tmpCode = gmp_xor($tmpCode, (gmp_and(gmp_mul($tmpChar, "32"), "0x01FE0"))); $tmpCode = gmp_add(gmp_xor($tmpCode, $tmpChar), "3"); } return gmp_and($tmpCode, "0xFFFFFFFF"); } function int2code($intCode) { $tmpCode = gmp_and($intCode, "0xFFFFFFFF"); $i = 0; $code = ''; while ($i < 7) { $tmpByte = gmp_intval(gmp_mod($tmpCode, "0x24")); if ($tmpByte < 10) { $code = chr(ord('0') + (int)$tmpByte) . $code; } else { $code = chr(ord('A') + (int)$tmpByte - 10) . $code; } $tmpCode = gmp_div_q(gmp_mul($tmpCode, "0x38E38E39"), 8); $tmpCode = gmp_div_q(gmp_and($tmpCode, "0xFFFFFFFF00000000"), "4294967296"); $i++; } return $code; } function cryptUserPass($password, $userName) { $tmpConst = "0xA59C29F1"; $tmpCode = gmp_xor(str2Int($userName . $password), $tmpConst); $code = int2Code($tmpCode); $tmpConst = gmp_and(gmp_add("0x928379A1", $tmpCode), "0xFFFFFFFF"); $tmpCode = gmp_xor(str2Int($password), $tmpConst); $code = $code . Int2Code($tmpCode); return $code; } print_r(cryptUserPass('hello', 'jw02')); echo "\n" . '0OYMDGB17QNP49' . "\n"; |
Or if you have a 64-bit PHP binary:
#!/usr/bin/php <?php echo "PHP_INT_SIZE: " . PHP_INT_SIZE . "\n"; function str2int($string) { $string = strtolower($string); $tmpCode = 0x015A4E35; for ($i = 0; $i < strlen($string); $i++) { $tmpChar = ord($string[$i]) & 0xff; $tmpCode = $tmpCode & 0xFFFFFFFF; $tmpCode = (($tmpCode << 13) & 0x0FFFFE000) + (($tmpCode >> 19) & 0x000001FFF); $tmpCode = $tmpCode ^ (($tmpChar << 5) & 0x01FE0); $tmpCode = ($tmpCode ^ $tmpChar) + 3; } return $tmpCode & 0xFFFFFFFF; } function int2code($intCode) { $tmpCode = $intCode & 0xFFFFFFFF; $i = 0; $code = ''; while ($i < 7) { $tmpByte = $tmpCode % 0x24; if ($tmpByte < 10) { $code = chr(ord('0') + (int)$tmpByte) . $code; } else { $code = chr(ord('A') + (int)$tmpByte - 10) . $code; } $tmpCode = ($tmpCode * 0x38E38E39) >> 3; $tmpCode = ($tmpCode & 0xFFFFFFFF00000000) >> 32; $i++; } return $code; } function cryptUserPass($password, $userName) { $tmpConst = 0xA59C29F1; $tmpCode = str2Int($userName . $password) ^ $tmpConst; $code = int2Code($tmpCode); $tmpConst = (0x928379A1 + $tmpCode) & 0xFFFFFFFF; $tmpCode = str2Int($password) ^ $tmpConst; $code = $code . Int2Code($tmpCode); return $code; } print_r(cryptUserPass('hello', 'jw02')); echo "\n" . '0OYMDGB17QNP49' . "\n"; |
You probably don’t need this, but if you do, it’s a lifesaver.
Originally found in delphi. In Russian.
[…] Hashing Axapta 3 compatible passwords from PHP | blog.rhp.org blog.rhp.org/2009/08/21/hashing-axapta-3-compatible-passwords-from-php – view page – cached Hashing Axapta 3 compatible passwords from PHP, As an interlude from the CoughPHP, I present the following: The downside of working with legacy systems is that sometimes you find it necessary to work with — From the page […]