PHP md5() for login page

If this has been asked before, I apologize. I have spent countless hours searching through google and on this site for this answer:

I have created an external php page for both registering and logging in clients. I modifed the login.html file on the hotspot to pass the id and challenge, I have tried to concatenate chap-id, password, and chap-challenge utilizing the following in my external php file $pwd = $chapid.$password.$chapchallenge. An echo of $pwd is:
\051test\333\311\130\244\370\106\344\017\263\167\057\152\317\114\013\323 where \051 is the chap-id and test was the password. The conversion does not match and chap fails.
I modifed the login.html file on the hotspot to display the chap password which was c5cc6920e01c5cbf0545b42e1c551111. php md5() displayed 445a83713211579469e2f2577697d64b. I’m obviously lost.
I can’t get php to pass variables to functions and an external javascript file (md5.js) so I am unable to utilize this in my script.
My thoughts are that the \ need to be stripped and converted to something else before md5()???

Help would be most appreciated!

Sorry, it should read $pwd = md5($chapid.$password.$chapchallenge);

I know someone has run into this and figured it out. I am going to try calling a plain html file from php with MT’s index.html code in it passing the necessary variables.

Does MT generate another chap-id as soon as you click submit and prior to calling doLogin()?
chap-id and chap-challenge are both set once the redirect occurs but if it generated another as soon as the external page called MT/login, this could be the problem.

Another note, I also tried PERL’s Crypt/CHAP.php as follows:
require_once ‘Crypt/CHAP.php’;
$cr = new Crypt_CHAP_MD5();
$cr->id = $_REQUEST[‘chap-id’];
$cr->password = $_REQUEST[‘spassword’];
$cr->challenge = $_REQUEST[‘chap-challenge’];
$pwrd = bin2hex($cr->challengeResponse());

Still no go.

I resolved the issue by creating a much simpler file for authorization and my script just calls this new file with the variables passed in the session. Still would like to know what the md5.js does different then php’s md5() so that I could do everything in one file.

Hi. for This reason, I’m also really interested in doing MD5 hashing, inside the php and not by a client-side script. this should be possible as otherwise, This method, wouldn’t work either. Although i don’t know anything about javascript at this point, but we have access to the source code (md5.js). shouldn’t be that hard to figure out what’s going on there.

For those who might be interested, i finally could make the md5 hash work through php. the thing to notice is that those \nnn are not normal characters. each of those represent an octal value. to make the correct md5 hash with php, you need to do it like this:

$hash = md5("chap-id".password."chap-challenge");

for example:

$hash = md5("\373".'test'."\314\135\024\000\354\025\252\076\261\347\222\151\146\002\250\265");

hope it could help someone cause although it seems simple, i spent countless hours finding the problem and looking for the best solution.

Edit: generating a correct md5 hash from $_POST is more complicated than that. go to http://forum.mikrotik.com/viewtopic.php?p=276099#p276099 for more detail.

Thanks for documenting your solution but your response:
$hash = md5(“\373”.‘test’.“\314\135\024\000\354\025\252\076\261\347\222\151\146\002\250\265”);
is too subtle for me.

How does that differ from:
$pwd = md5($chapid.$password.$chapchallenge);
???

In particular since the chap-id and chap-challenge are not hard coded but come in variables. I tried this:
$pwd = md5(‘"’.$chapid.‘"’.$password.‘"’.$chapchallenge.‘"’);
But this did not bring any improvement.

Can you please advise your precise php code?

Did you read the link i provided in my post in “Edit:” part? that link contains a php code example.
To be more precise, when you save those octave numbers in a variable, they end up as a string. extra step is needed to convert them before generating md5.

But this did not bring any improvement.

How is it failing? Did you remember to copy your md5.js file to your server? If it isn’t there, it won’t work.

edit: How do you plan on getting the PHP code to the client so the password can be encrypted before sending it to the router hotspot? And once you get it there, how do you plan on running it? PHP is server side code, and JavaScript is client side code.

Yes, the code in here is working OK:
http://forum.mikrotik.com/t/what-exactly-are-chap-id-chap-challenge/49318/3

With a fixed password, it would. If you expect the user to enter a unique password and have it encrypted, that would be best achieved by the md5.js script.

I thought this topic sounded familiar.

My solution :slight_smile: :

#!/usr/bin/php5
<?php
class  LoginMikrotik {
	var $urlLogin = 'http://hostpot.com/login';
	var $urlLogout = 'http://hostpot.com/logout';
	var $myPassword = 'secret';
	var $myUsername = 'username';
	
	function genChapPassword() {
		// create curl resource
		$ch = curl_init();
		// set url
		curl_setopt($ch, CURLOPT_URL, $this->urlLogin);
		//return the transfer as a string
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		// $output contains the output string
		$output = curl_exec($ch);
		// close curl resource to free up system resources
		curl_close($ch);
		$lines = explode(PHP_EOL, $output);
		foreach ($lines as $line) {
			if (strpos($line, 'hexMD5')) {
				$match = array();
				preg_match('/\'([^\']*)\'.*\'([^\']*)\'/', $line, $match);
				if(count($match) == 3) {
					$pass = '';
					$chapId = utf8_decode($match[1]);
					$chapChallenge = utf8_decode($match[2]);
					eval("\$pass = md5(\"$chapId\" . \$this->myPassword . \"$chapChallenge\");");
					return $pass;
				}
			}
		}
		return false;
	}


	function login() {
		$password = $this->genChapPassword();
		if(!$password) {
			echo "Error!";
		}
		$ch = curl_init();
		// set url
		curl_setopt($ch, CURLOPT_URL,$this->urlLogin);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, "username=".$this->myUsername."&password=" . $password . "&popup=true&dst=");
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		$server_output = curl_exec ($ch);
		$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close ($ch);
		echo "\ncode: " . $httpcode;
		echo "\noutput: " . $server_output;
	}

	function logout() {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $this->urlLogout);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		$output = @curl_exec($ch);
		curl_close($ch);
		return $output;
	}

}


#using:
echo "action: " . $argv[1] . "\n";
$login = new LoginMikrotik();

switch ($argv[1]) {
	case 'start':
		$login->login();
		break;
	case 'stop':
		$login->logout();
		exit(0);
		break;
	default :
		break;
}

get code: https://gist.github.com/fitorec/c3d5495327d982095667