I am trying to write a Java program that reads a password from a user, hashes it, then sends it to a PHP script on my website. This PHP script compares the hashed password in the database to the one passed to the script.
According this this answer on Stackoverflow, Joomla! uses PHPass to encrypt passwords, rather than the previous MD5. What I need to do, is encrypt the password in the Java application, and send the hashed version to the server to check. I found this port of PHPass in Java. I tested it out, but sadly, it does not work.
I have a user, test
with the password test
set up on my Joomal! site. In the database, the password is:
$2y$10$d8TS1ghHSGPqpxtmzgvsN.905fIbgZqtICvaQzKDSl2bNaEbQy7ZW
But using PHPass (in Java), the output hash is:
$S$DNrrYw1XFU2dAKUaQhiJV/1eYBYvQHEMOJtqatuo0LJ8JG/WhK54
This is the script I am using on my website to test the passwords, checkuser.php
(http://neonorb.com/software/checkuser.php), (sorry about the bad formatting):
<?php
include('checkuserfunction.php');
echo checkUser($_GET['user'], $_GET['pass'], $_GET['package']);
?>
checkuserfunction.php
(http://neonorb.com/software/checkuserfunction.php), (sorry about the bad formatting):
<?php
function checkUser($user, $pass, $package){
/**
* Joomla! External authentication script
*
* @author vdespa
* Version 1.0
*
* Code adapted from /index.php
*
* @package Joomla.Site
*
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
if (version_compare(PHP_VERSION, '5.3.1', '<'))
{
die('Your host needs to use PHP 5.3.1 or higher to run this version of Joomla!');
}
/**
* Constant that is checked in included files to prevent direct access.
* define() is used in the installation folder rather than "const" to not error for PHP 5.2 and lower
*/
define('_JEXEC', 1);
if (file_exists(__DIR__ . '/defines.php'))
{
include_once __DIR__ . '/defines.php';
}
if (!defined('_JDEFINES'))
{
define('JPATH_BASE', '/home4/neonorb/public_html');
require_once JPATH_BASE . '/includes/defines.php';
}
require_once JPATH_BASE . '/includes/framework.php';
// Instantiate the application.
$app = JFactory::getApplication('site');
// JFactory
require_once (JPATH_BASE .'/libraries/joomla/factory.php');
$credentials['username'] = $user;
$credentials['password'] = $pass;
/**
* Code adapted from plugins/authentication/joomla/joomla.php
*
* @package Joomla.Plugin
* @subpackage Authentication.joomla
*
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// Get a database object
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('id, password')
->from('#__users')
->where('username=' . $db->quote($credentials['username']));
$db->setQuery($query);
$result = $db->loadObject();
if ($result)
{
echo $credentials['password']."<br>";
echo $result->password."<br>";
//$match = JUserHelper::verifyPassword($credentials['password'], $result->password, $result->id);
$match = $credentials['password'] == $result->password;
$id = $result->id;
jimport( 'joomla.access.access' );
$groups = JAccess::getGroupsByUser($id, false);
$db = JFactory::getDbo();
$db->setQuery(
'SELECT `id` FROM `#__usergroups` WHERE \''.$package.'\' = title'
);
$groupid .= $db->loadResult();
if ($match === true)
{
// Bring this in line with the rest of the system
$user = JUser::getInstance($result->id);
if(in_array($groupid, $groups)){
return 1;
}else{
return 2;
}
}else{
return 0;
}
} else {
return 0;
}
}
?>
I call this script like this:
checkuser.php?user=<username>&pass=<hashed-password>&package=derby-pro-paid
The package
thing is to test to see if that particular user has paid for the package, for our purposes, it will always be derby-pro-paid
.
The first line printed is the password entered to the function, the second, the one stored in the database. The third, the return of the function.
Returning 0
means that the password was incorrect. 1
means that the password was correct. 2
is unneeded for this, it means that the user has not paid for that package. As long as package
is set to derby-pro-paid
, it should never return 2
.
Here is my code for calling the hash method in Java:
PasswordHasher passwordHasher = new PasswordHasher();
Log.debug(passwordHasher.createHash("test"));
Why doesn't this Java method of creating Joomla! hashes work correctly?