Password encryption changed from RC1 to RC7?

Get help with installation and running phpBB 3.0.x here. Please do not post bug reports, feature requests, or MOD-related questions here.
Anti-Spam Guide
Forum rules
END OF SUPPORT: 1 January 2017 (announcement)
User avatar
Marshalrusty
Project Manager
Project Manager
Posts: 29253
Joined: Mon Nov 22, 2004 10:45 pm
Location: New York City
Name: Yuriy Rusko
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Marshalrusty »

Timmer wrote:The first person who replied told me it would be "pretty straight forward to port to Perl." Now you are saying it is not.
That's because easiness is relative.

If you are an experienced php and Perl programmer, then it's just a matter of mimicking the code, which is not particularly difficult. However, you do have to understand how the mechanism works. I do not have much experience with Perl, so for me this would require lots of trial and error.

As I said, you might want to try posting on a board dedicated to coding in Perl.
Have comments/praise/complaints/suggestions? Please feel free to PM me.

Need private help? Hire me for all your phpBB and web development needs

User avatar
EXreaction
Former Team Member
Posts: 5666
Joined: Sun Aug 21, 2005 9:31 pm
Location: Wisconsin, U.S.
Name: Nathan

Re: Password encryption changed from RC1 to RC7?

Post by EXreaction »

If you ask on Perl support forums I am sure someone will be able to help you.

The problem with asking here is that, for the most part, if anyone knows how to code it will be PHP, probably not Perl.

User avatar
Timmer
Registered User
Posts: 112
Joined: Fri Sep 24, 2004 4:21 pm
Location: Portland, OR
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Timmer »

Thanks for the replies. I can't argue with what you guys are saying.

This is my plan: I'm going to install a fresh copy of PHPBB3 in a test area so I can play with it, add some debug prints, etc. so I can track what is in some of the variables as they go through hashing. Hopefully this will help me understand what the new hashing mechanism is doing.

If I'm successful, I'll return and share my Perl code in this thread for everyone's potential benefit.

Freeco
Registered User
Posts: 14
Joined: Thu Mar 01, 2007 4:03 pm
Location: Belgium
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Freeco »

actually, I need about the same thing for my ASP website...
I had created some sort of (basic) community pages on the site, simply logging in with the same credentials from phpBB2. I had the MD5-coded in ASP, but seems I'll have to change that since I migrated the forum to 3.0 yesterday...
Still nobody has figured it out? I'm not that much of a PHP wizard (Perl even less :roll:), so chances are small I'll be able to solve this myself :|

EnFuego
Registered User
Posts: 33
Joined: Mon Jan 17, 2005 10:01 pm

Re: Password encryption changed from RC1 to RC7?

Post by EnFuego »

[edit: Ignore my original thoughts. I was being stupid. Below, I've included a portion of a script that would validate a password based on taking a user's input and checking it against the database hash. Now, this is in PHP coding, but I'm sure you could adapt it to Perl.]

Code: Select all

// Assumes you've accepted the password
// as $password and username as $username
// prior to calling the check_auth function
function check_auth($username, $password)
{
	$host = 'somehost';
	$sqluser = 'someuser';
	$sqlpass = 'somepass';

	$good_auth = false;

	$sql = "SELECT user_password FROM db.phpbb_users WHERE username='" . $username . 

"'";
	$link = mysql_connect($host, $sqluser, $sqlpass);
	if (!$link)
	{
		die("Could not connect");
	}
	$result = mysql_query($sql);
	$row = mysql_fetch_row($result);
	$dbhash = $row[0];

	$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
	
	if (strlen($dbhash) == 34)
	{
		$pwhash = hash_it($password, $dbhash, $itoa64);
	} else {
		$pwhash = md5($password);
	}

	if ($pwhash === $dbhash)
	{
		$good_auth = true;
	}
	
	return $good_auth;
}



// This is copy/paste of phpBB's
// _hash_crypt_private function
function hash_it($password, $setting, &$itoa64)
{
	$output = '*';

	// Check for correct hash
	if (substr($setting, 0, 3) != '$H$')
	{
		return $output;
	}

	$count_log2 = strpos($itoa64, $setting[3]);

	if ($count_log2 < 7 || $count_log2 > 30)
	{
		return $output;
	}

	$count = 1 << $count_log2;
	$salt = substr($setting, 4, 8);

	if (strlen($salt) != 8)
	{
		return $output;
	}

	/**
	* We're kind of forced to use MD5 here since it's the only
	* cryptographic primitive available in all versions of PHP
	* currently in use.  To implement our own low-level crypto
	* in PHP would result in much worse performance and
	* consequently in lower iteration counts and hashes that are
	* quicker to crack (by non-PHP code).
	*/
	if (PHP_VERSION >= 5)
	{
		$hash = md5($salt . $password, true);
		do
		{
			$hash = md5($hash . $password, true);
		}
		while (--$count);
	}
	else
	{
		$hash = pack('H*', md5($salt . $password));
		do
		{
			$hash = pack('H*', md5($hash . $password));
		}
		while (--$count);
	}

	$output = substr($setting, 0, 12);
	$output .= _hash_encode64($hash, 16, $itoa64);

	return $output;
}

// Copy/paste of phpBB's function
function _hash_encode64($input, $count, &$itoa64)
{
	$output = '';
	$i = 0;

	do
	{
		$value = ord($input[$i++]);
		$output .= $itoa64[$value & 0x3f];

		if ($i < $count)
		{
			$value |= ord($input[$i]) << 8;
		}

		$output .= $itoa64[($value >> 6) & 0x3f];

		if ($i++ >= $count)
		{
			break;
		}

		if ($i < $count)
		{
			$value |= ord($input[$i]) << 16;
		}

		$output .= $itoa64[($value >> 12) & 0x3f];
		
		if ($i++ >= $count)
		{
			break;
		}

		$output .= $itoa64[($value >> 18) & 0x3f];
	}
	while ($i < $count);

	return $output;
}

User avatar
Timmer
Registered User
Posts: 112
Joined: Fri Sep 24, 2004 4:21 pm
Location: Portland, OR
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Timmer »

I just wanted to say thank you for your efforts on this. Your post is MUCH appreciated.

I'm not sure if it will help my Perl script or not. Someone else mentioned there might be a way to have my Perl script call the PHP function. If so, that might work if I can figure out what you've posted. I'll try to play with it.

Freeco
Registered User
Posts: 14
Joined: Thu Mar 01, 2007 4:03 pm
Location: Belgium
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Freeco »

thanks a lot enfuengo! I'll definitelly try that one out!
at first sight this code seem easier to understand for my basic php skills :D

EnFuego
Registered User
Posts: 33
Joined: Mon Jan 17, 2005 10:01 pm

Re: Password encryption changed from RC1 to RC7?

Post by EnFuego »

Timmer wrote:I just wanted to say thank you for your efforts on this. Your post is MUCH appreciated.

I'm not sure if it will help my Perl script or not. Someone else mentioned there might be a way to have my Perl script call the PHP function. If so, that might work if I can figure out what you've posted. I'll try to play with it.
How about something along the lines of the following?
(Note, I was unable to install PHP::Interpreter on my system, as it didn't like my PHP install, but based on the documentation for PHP::Interpreter, this code should work or at least come REALLY close!)

And Frecco, I'm sorry, but I don't know JACK about ASP. :mrgreen:

Code: Select all

#!/usr/bin/perl -w
use DBI;
use PHP::Interpreter;

#
# Your main code goes here
#

# -- Your authorization subroutine --
# Assumes you've passed the user and pass
# variables in the subroutine call!
sub check_auth {

   $username = $_[0];
   $password = $_[1];
   $sqluser = 'sqluser';
   $sqlpass = 'sqlpass';

   $good_auth = 0;

   # Make sure to replace "mydbname" with
   # your actual database name!!
   $dbh = DBI->connect('dbi:mysql:mydbname',$sqluser,$sqlpass)
        or die "Connection Error: $DBI::errstr\n";

   $sql = "SELECT user_password FROM phpbb_users WHERE username='" . $username . "'";
   $sth = $dbh->prepare($sql);                                                  
   $sth->execute
        or die "SQL Error: $DBI::errstr\n";
   @row = $sth->fetchrow_array;
   $dbhash = $row[0];

   $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
   $php = new PHP::Interpreter();
   # Path can be something such as:
   # "../phpbb3/includes/functions.php"
   $php->include("/path/to/phpbb3/includes/functions.php");
   if (length($dbhash) == 34)
   {
      $pwhash = $php->_hash_crypt_private($password, $dbhash, $itoa64);
   } else {
      $pwhash = md5($password);
   }

   if ($pwhash eq $dbhash)
   {
      $good_auth = 1;
   }

   return $good_auth;
}

SandyT
Registered User
Posts: 22
Joined: Tue Nov 11, 2003 8:40 pm

Re: Password encryption changed from RC1 to RC7?

Post by SandyT »

I also have a custom-build Perl system that has user accounts. I too wanted to eliminate the redundant user account system so I only had one account per user to manage and support. I came up with the following solution that allows my Perl script to compare the login name and password to the values saved in the phpBB users table. This involved translating some of the phpBB password hashing alogorithms from PHP into Perl.

This solution definitely works with phpBB3 and should work with phpBB2 as well. However, on versions of phpBB3 that were upgraded from phpBB2, I've got a niggle that this will only work with accounts that have been logged into at least once using the standard forum login. There's a password conversion that takes place during each user's first login following the upgrade. It may even work in that event, but who knows? I don't have any non-converted accounts to check it out, nor do I care to try and fake one.

The code follows. I've written a tiny sample program that uses the functions. Generalized usage will be obvious to Perl programmers. Feel free to PM me with questions about it.

Sandy

Code: Select all

#!/usr/bin/perl -w
use DBI;
use Digest::MD5 qw(md5);

# These hard-coded test values would likely be inputs from your login form
my $InputUsername = "Sandy";
my $InputPassword = "<mypassword>";

my $DatabaseHandle = DBI->connect("<myDBURL>", "<myDBUser>", "<myDBPassword>") or die "Couldn't connect to database: $DBI::errstr";

my $SQLStatement = "SELECT user_password FROM phpbb3_users WHERE username=?";
my $StatementHandle = $DatabaseHandle->prepare($SQLStatement);                                                  
$StatementHandle->execute($InputUsername) or die "SQL Error: $DBI::errstr\n";
my @UserRow = $StatementHandle->fetchrow_array;
my $DBPasswordHash = $UserRow[0];

print "Authorization Succeeded: " . &ComparePasswords($InputPassword, $DBPasswordHash);

exit;




sub ComparePasswords
{
   my $password = $_[0];
   my $dbhash = $_[1];
   my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

   my $pwhash;
   if (length($dbhash) == 34)
   {
      $pwhash = _hash_crypt_private($password, $dbhash, $itoa64);
   }
   else
   {
      $pwhash = md5($password);
   }
   
   return ($pwhash eq $dbhash) ? 1 : 0;
}

sub _hash_crypt_private
{
   my $password = $_[0];
   my $setting = $_[1];
   my $ITOA64 = $_[2];
   my $output = "*";

   if (substr($setting, 0, 3) ne "\$H\$")
   {
      return $output;
   }
   
   my $count_log2 = index($ITOA64, substr($setting, 3, 1));
   
   if ($count_log2 < 7 || $count_log2 > 30)
   {
      return $output;
   }
   
   my $count = 1 << $count_log2;
   my $salt = substr($setting, 4, 8);

   if (length($salt) != 8)
   {
      return $output;
   }
   
   my $hash = md5($salt . $password);
   do
   {
      $hash = md5($hash . $password);
   }
   while (--$count);
   
   $output = substr($setting, 0, 12);
   $output .= _hash_encode64($hash, 16, $ITOA64);
   
   return $output;
}


sub _hash_encode64
{
   my $input = $_[0];
   my $count = $_[1];
   my $ITOA64  = $_[2];
   
   my $output = "";
   my $i = 0;

   do
   {
      my $value = ord(substr($input, $i++, 1));
      $output .= substr($ITOA64, $value & 0x3f, 1);
    
      if ($i < $count)
      {
         $value |= ord(substr($input, $i, 1)) << 8;
      }
     
      $output .= substr($ITOA64, ($value >> 6) & 0x3f, 1);
      
      if ($i++ >= $count)
      {
         return $output;
      }
      
      if ($i < $count)
      {
         $value |= ord(substr($input, $i, 1)) << 16;
      }
      
      $output .= substr($ITOA64, ($value >> 12) & 0x3f, 1);
      
      if ($i++ >= $count)
      {
         return $output;
      }
         
      $output .= substr($ITOA64, ($value >> 18) & 0x3f, 1);
   }
   while ($i < $count);

   return $output;
}

User avatar
madjamonline
Registered User
Posts: 13
Joined: Tue Jan 01, 2008 5:57 pm
Location: Gloucestershire, United Kingdom
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by madjamonline »

EnFuego wrote:[edit: Ignore my original thoughts. I was being stupid. Below, I've included a portion of a script that would validate a password based on taking a user's input and checking it against the database hash. Now, this is in PHP coding, but I'm sure you could adapt it to Perl.]
You are a life saver! Thank-you so much! :D
Jamie
Head of Madjamonline
http://www.madjamonline.com

User avatar
Timmer
Registered User
Posts: 112
Joined: Fri Sep 24, 2004 4:21 pm
Location: Portland, OR
Contact:

Re: Password encryption changed from RC1 to RC7?

Post by Timmer »

SandyT, I can confirm your Perl code worked for me. Thanks a million!

Locked

Return to “[3.0.x] Support Forum”