Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
scrypt-lib
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
onibi-composer
scrypt-lib
Commits
f3c771a2
Commit
f3c771a2
authored
Dec 19, 2014
by
Mark Garrett
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Actually get it working right. Added needsRehash() function to mimic password_needs_rehash()
parent
3c69cdd3
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
21 deletions
+86
-21
.gitignore
+3
-0
library/Scrypt.php
+83
-21
No files found.
.gitignore
0 → 100644
View file @
f3c771a2
.idea
vendor
composer.lock
library/Scrypt.php
View file @
f3c771a2
<?php
<?php
namespace
ModDev\Password
;
namespace
ModDev\Password
;
use
Traversable
;
use
Zend\Crypt\Exception\InvalidArgumentException
;
use
Zend\Crypt\Exception\InvalidArgumentException
;
use
Zend\Crypt\Key\Derivation\Scrypt
as
DerivationScrypt
;
use
Zend\Crypt\Key\Derivation\Scrypt
as
DerivationScrypt
;
use
Zend\Crypt\Password\PasswordInterface
;
use
Zend\Crypt\Password\PasswordInterface
;
use
Zend\Crypt\Utils
;
use
Zend\Crypt\Utils
;
use
Zend\Math\Rand
;
use
Zend\Math\Rand
;
use
Zend\Stdlib\ArrayUtils
;
/**
/**
* Class to implement scrypt hashing in the Phalcon framework. This provides hashes that are
* Class to implement scrypt hashing in PHP. This provides hashes that use the same MCF as
* in the same MCF as {@see https://github.com/wg/scrypt} - a Java implementation of scrypt.
* {@see https://github.com/wg/scrypt} - a Java implementation of scrypt. While it utilizes a handful of Zend Framework
* classes, this is not restricted to ZF2 projects.
*
*
* @see http://www.tarsnap.com/scrypt.html
* @see http://www.tarsnap.com/scrypt.html
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
* @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
...
@@ -19,7 +22,7 @@ class Scrypt implements PasswordInterface
...
@@ -19,7 +22,7 @@ class Scrypt implements PasswordInterface
{
{
/**
/**
* The MCF identifier for this version of the hashing algorith
i
m.
* The MCF identifier for this version of the hashing algorithm.
*/
*/
const
HASH_MFC_VERSION
=
's0'
;
const
HASH_MFC_VERSION
=
's0'
;
...
@@ -47,9 +50,9 @@ class Scrypt implements PasswordInterface
...
@@ -47,9 +50,9 @@ class Scrypt implements PasswordInterface
* Constructor
* Constructor
*
*
* @param array|Traversable $options
* @param array|Traversable $options
* @throws
Exception\
InvalidArgumentException
* @throws InvalidArgumentException
*/
*/
public
function
__construct
(
$options
=
[]
)
public
function
__construct
(
$options
=
array
()
)
{
{
if
(
!
empty
(
$options
))
{
if
(
!
empty
(
$options
))
{
if
(
$options
instanceof
Traversable
)
{
if
(
$options
instanceof
Traversable
)
{
...
@@ -59,6 +62,9 @@ class Scrypt implements PasswordInterface
...
@@ -59,6 +62,9 @@ class Scrypt implements PasswordInterface
'The options parameter must be an array or a Traversable'
'The options parameter must be an array or a Traversable'
);
);
}
}
krsort
(
$options
);
foreach
(
$options
as
$key
=>
$value
)
{
foreach
(
$options
as
$key
=>
$value
)
{
switch
(
strtolower
(
$key
))
{
switch
(
strtolower
(
$key
))
{
case
'cpudifficulty'
:
case
'cpudifficulty'
:
...
@@ -101,7 +107,6 @@ class Scrypt implements PasswordInterface
...
@@ -101,7 +107,6 @@ class Scrypt implements PasswordInterface
*
*
* @param string $password The clear text password
* @param string $password The clear text password
* @param string $hash The hashed password
* @param string $hash The hashed password
*
* @return boolean If the clear text matches
* @return boolean If the clear text matches
*/
*/
public
function
verify
(
$password
,
$hash
)
public
function
verify
(
$password
,
$hash
)
...
@@ -118,9 +123,7 @@ class Scrypt implements PasswordInterface
...
@@ -118,9 +123,7 @@ class Scrypt implements PasswordInterface
return
false
;
return
false
;
}
}
$N
=
(
int
)
pow
(
2
,
hexdec
(
substr
(
$params
,
0
,
-
4
)));
list
(
$N
,
$r
,
$p
)
=
$this
->
splitParams
(
$params
);
$r
=
(
int
)
substr
(
$params
,
-
4
,
2
);
$p
=
(
int
)
substr
(
$params
,
-
2
,
2
);
// Any empty fields?
// Any empty fields?
if
(
empty
(
$salt
)
||
empty
(
$hash
)
||
!
is_numeric
(
$N
)
||
!
is_numeric
(
$r
)
or
!
is_numeric
(
$p
))
{
if
(
empty
(
$salt
)
||
empty
(
$hash
)
||
!
is_numeric
(
$N
)
||
!
is_numeric
(
$r
)
or
!
is_numeric
(
$p
))
{
...
@@ -129,11 +132,13 @@ class Scrypt implements PasswordInterface
...
@@ -129,11 +132,13 @@ class Scrypt implements PasswordInterface
$calculated
=
DerivationScrypt
::
calc
(
$password
,
base64_decode
(
$salt
),
$N
,
$r
,
$p
,
$this
->
getKeyLength
());
$calculated
=
DerivationScrypt
::
calc
(
$password
,
base64_decode
(
$salt
),
$N
,
$r
,
$p
,
$this
->
getKeyLength
());
// Use compareStrings to avoid tim
e
ing attacks
// Use compareStrings to avoid timing attacks
return
Utils
::
compareStrings
(
base64_decode
(
$encodedHash
),
$calculated
);
return
Utils
::
compareStrings
(
base64_decode
(
$encodedHash
),
$calculated
);
}
}
/**
/**
* Return the CPU difficulty
*
* @return int
* @return int
*/
*/
public
function
getCpuDifficulty
()
public
function
getCpuDifficulty
()
...
@@ -142,6 +147,8 @@ class Scrypt implements PasswordInterface
...
@@ -142,6 +147,8 @@ class Scrypt implements PasswordInterface
}
}
/**
/**
* Set the CPU difficulty. This also checks validity of the input.
*
* @param int $cpuDifficulty
* @param int $cpuDifficulty
*/
*/
public
function
setCpuDifficulty
(
$cpuDifficulty
)
public
function
setCpuDifficulty
(
$cpuDifficulty
)
...
@@ -150,10 +157,16 @@ class Scrypt implements PasswordInterface
...
@@ -150,10 +157,16 @@ class Scrypt implements PasswordInterface
throw
new
InvalidArgumentException
(
"cpuDifficulty must be > 0 and a power of 2"
);
throw
new
InvalidArgumentException
(
"cpuDifficulty must be > 0 and a power of 2"
);
}
}
if
(
$cpuDifficulty
>
(
PHP_INT_MAX
/
128
/
$this
->
getMemoryDifficulty
()))
{
throw
new
InvalidArgumentException
(
"cpuDifficulty is too large"
);
}
$this
->
cpuDifficulty
=
$cpuDifficulty
;
$this
->
cpuDifficulty
=
$cpuDifficulty
;
}
}
/**
/**
* Return the memory difficulty
*
* @return int
* @return int
*/
*/
public
function
getMemoryDifficulty
()
public
function
getMemoryDifficulty
()
...
@@ -162,18 +175,25 @@ class Scrypt implements PasswordInterface
...
@@ -162,18 +175,25 @@ class Scrypt implements PasswordInterface
}
}
/**
/**
* Set the memory difficulty. This also checks the validity of the input and validity of the CPU difficulty based on
* the new memory difficulty number.
*
* @param int $memoryDifficulty
* @param int $memoryDifficulty
*/
*/
public
function
setMemoryDifficulty
(
$memoryDifficulty
)
public
function
setMemoryDifficulty
(
$memoryDifficulty
)
{
{
if
(
$
n
>
PHP_INT_MAX
/
128
/
$memoryDifficulty
)
{
if
(
$
memoryDifficulty
>
(
PHP_INT_MAX
/
128
/
$this
->
getParallelDifficulty
())
)
{
throw
new
InvalidArgumentException
(
"
memory
Difficulty is too large"
);
throw
new
InvalidArgumentException
(
"
parallel
Difficulty is too large"
);
}
}
$this
->
memoryDifficulty
=
$memoryDifficulty
;
$this
->
memoryDifficulty
=
$memoryDifficulty
;
//CPU Difficulty has a check that relies on memory difficulty, so we need to check that we are still fine.
$this
->
setCpuDifficulty
(
$this
->
cpuDifficulty
);
}
}
/**
/**
* Return the parallel difficulty
*
* @return int
* @return int
*/
*/
public
function
getParallelDifficulty
()
public
function
getParallelDifficulty
()
...
@@ -182,15 +202,17 @@ class Scrypt implements PasswordInterface
...
@@ -182,15 +202,17 @@ class Scrypt implements PasswordInterface
}
}
/**
/**
* Set the parallel difficulty. This also checks the validity of the memory difficulty based on the new parallel
* difficulty number.
*
* @param int $parallelDifficulty
* @param int $parallelDifficulty
*/
*/
public
function
setParallelDifficulty
(
$parallelDifficulty
)
public
function
setParallelDifficulty
(
$parallelDifficulty
)
{
{
if
(
$r
>
PHP_INT_MAX
/
128
/
$parallelDifficulty
)
{
throw
new
InvalidArgumentException
(
"parallelDifficulty is too large"
);
}
$this
->
parallelDifficulty
=
$parallelDifficulty
;
$this
->
parallelDifficulty
=
$parallelDifficulty
;
//Memory Difficulty has a check that relies on parallel difficulty, so we need to check that we are still fine.
$this
->
setMemoryDifficulty
(
$this
->
memoryDifficulty
);
}
}
/**
/**
...
@@ -206,7 +228,7 @@ class Scrypt implements PasswordInterface
...
@@ -206,7 +228,7 @@ class Scrypt implements PasswordInterface
*/
*/
public
function
setKeyLength
(
$keyLength
)
public
function
setKeyLength
(
$keyLength
)
{
{
if
(
$keyLength
>
16
)
{
if
(
$keyLength
<
16
)
{
throw
new
InvalidArgumentException
(
"Key length is too low, must be greater or equal to 16"
);
throw
new
InvalidArgumentException
(
"Key length is too low, must be greater or equal to 16"
);
}
}
...
@@ -218,16 +240,14 @@ class Scrypt implements PasswordInterface
...
@@ -218,16 +240,14 @@ class Scrypt implements PasswordInterface
* scrypt.
* scrypt.
*
*
* @param string $hash The hashed password
* @param string $hash The hashed password
*
* @return string The hash algorithm. Returns 'unknown' if hash type not found.
* @return string The hash algorithm. Returns 'unknown' if hash type not found.
*/
*/
public
function
getHashType
(
$hash
)
public
function
getHashType
(
$hash
)
{
{
$type
=
''
;
$hashParts
=
explode
(
'$'
,
$hash
);
$hashParts
=
explode
(
'$'
,
$hash
);
switch
(
$hashParts
[
1
])
{
switch
(
$hashParts
[
1
])
{
case
self
::
$hashMcfVersion
:
case
self
::
HASH_MFC_VERSION
:
$type
=
'scrypt'
;
$type
=
'scrypt'
;
break
;
break
;
...
@@ -259,4 +279,46 @@ class Scrypt implements PasswordInterface
...
@@ -259,4 +279,46 @@ class Scrypt implements PasswordInterface
return
$type
;
return
$type
;
}
}
/**
* Split out the algorithm parameters from a hashed password's parameter string
*
* @param string $params The parameter string
* @return array Array of parameters used to make this hash
*/
private
function
splitParams
(
$params
)
{
$N
=
(
int
)
pow
(
2
,
hexdec
(
substr
(
$params
,
0
,
-
4
)));
$r
=
(
int
)
hexdec
(
substr
(
$params
,
-
4
,
2
));
$p
=
(
int
)
hexdec
(
substr
(
$params
,
-
2
,
2
));
return
array
(
$N
,
$r
,
$p
);
}
/**
* Functionality similar to password_needs_rehash() to checks to see if current hash is using the latest parameters.
*
* @param $hash string The hash to check
* @return bool
*/
public
function
needsRehash
(
$hash
)
{
$hashParts
=
explode
(
'$'
,
$hash
);
if
(
$hashParts
[
1
]
!==
self
::
HASH_MFC_VERSION
)
{
return
true
;
}
list
(
$N
,
$r
,
$p
)
=
$this
->
splitParams
(
$hashParts
[
2
]);
if
(
$N
!==
$this
->
getCpuDifficulty
()
||
$r
!==
$this
->
getMemoryDifficulty
()
||
$p
!==
$this
->
getParallelDifficulty
()
)
{
return
true
;
}
return
false
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment