I am working on a legacy ColdFusion MX7 site. They want to implement a "salted hash" password system. But some time in the next year or so they plan to build a completely new PHP site and don't want to have to reset (lose) all the passwords.
So I'm looking for some code that will work on both platforms.
I'm new to this, but as far as I can tell, the following two blocks of code should do the same thing. However, they produce different results. Anyone care to help?
COLDFUSION CODE:
<cffunction name="computeHash" access="public" returntype="String">
<cfargument name="password" type="string" />
<cfargument name="salt" type="string" />
<cfargument name="iterations" type="numeric" required="false" default="1024" />
<cfargument name="algorithm" type="string" required="false" default="SHA-1" />
<cfscript>
var hashed = '';
hashed = hash( password & salt, arguments.algorithm, 'UTF-8' );
</cfscript>
<cfloop from="1" to="#iterations#" index="i">
<cfscript>
hashed = hash( hashed & salt, arguments.algorithm, 'UTF-8' );
</cfscript>
</cfloop>
</cffunction>
PHP CODE:
function computeHash($password,$salt)
{
$hashed = '';
$hashed = hash('sha1', $password . $salt);
for ($i = 1; $i <= 1024; $i++)
{
$hashed = hash('sha1', $hashed . $salt);
}
echo $hashed;
}
UPDATE 1: Thanks for your replies! Using a password of "p@ssW0rd", and a salt of "JjXSROiYyKkxNzTklaiErQ==" generates the following results:
COLDFUSION:
code, part 1:
hashed = hash( password & salt, arguments.algorithm, 'UTF-8' );
generates:
A0A8DE3A3B2A8BFD74766EEE126950F4462D3BCB
code, part 2:
hash( hashed & salt, arguments.algorithm, 'UTF-8' );
generates:
CFF9B75918B75761B5568854782CD709B2941637
PHP:
code, part 1:
$hashed = hash('sha1', $password . $salt);
generates:
a0a8de3a3b2a8bfd74766eee126950f4462d3bcb
code, part 2:
hash('sha1', $hashed . $salt);
generates:
e955404423747ec706561fa9a319ddac47194a65
As you can see, the first time around, the outputs match. But when I re-hash, they no longer match. I'm confused.
strtoupper()
on PHP's hash()
result - DCoder 2012-04-06 04:38
ColdFusion generates
A0A8DE3A3B2A8BFD74766EEE126950F4462D3BCB
, and PHP generates
a0a8de3a3b2a8bfd74766eee126950f4462d3bcb
As you can see, the first time around, the outputs match.
Those strings are not identical. You need to turn them both to the same case - I would use strtoupper()
on PHP's generated result.
Adobe's documentation for CF's hash
function does not list "SHA-1"
as a valid value for the algorithm
parameter. I guess you should be passing "SHA"
instead.
SHA
is just an alias for SHA-1
Leigh 2012-04-05 23:25
@DCoder nailed it. The problem was that ColdFusion was outputting all upper case, whereas PHP was outputting all lower case. So, using strtoupper() in the PHP code made them work identically. Also, SHA-512 seems to be supported in CF7 and PHP 5, so I'm switching to that algorithm. I'm including both the updated CF and PHP code below for future reference. :)
COLDFUSION CODE (unchanged except for algorithm):
<cffunction name="computeHash" access="public" returntype="String">
<cfargument name="password" type="string" />
<cfargument name="salt" type="string" />
<cfargument name="iterations" type="numeric" required="false" default="1024" />
<cfargument name="algorithm" type="string" required="false" default="SHA-512" />
<cfscript>
var hashed = '';
hashed = hash( password & salt, arguments.algorithm, 'UTF-8' );
</cfscript>
<cfloop from="1" to="#iterations#" index="i">
<cfscript>
hashed = hash( hashed & salt, arguments.algorithm, 'UTF-8' );
</cfscript>
</cfloop>
</cffunction>
PHP CODE (with strtoupper() added and new algorithm):
function computeHash($password,$salt)
{
$algorithm = 'sha512';
$hashed = '';
$hashed = strtoupper(hash($algorithm, $password . $salt));
for ($i = 1; $i <= 1024; $i++)
{
$hashed = strtoupper(hash($algorithm, $hashed . $salt));
}
echo $hashed';
}