Skip to content
Browse files

Added the scrypt key derivation algorithm

  • Loading branch information...
1 parent e5167b7 commit 19c78a5612e8827488b17d560d8bef7b2a97a50f @ezimuel committed Sep 27, 2012
View
4 library/Zend/Crypt/Hmac.php
@@ -42,10 +42,6 @@ class Hmac
*/
public static function compute($key, $hash, $data, $output = self::OUTPUT_STRING)
{
- if (!isset($key) || empty($key)) {
- throw new Exception\InvalidArgumentException('Provided key is null or empty');
- }
-
$hash = strtolower($hash);
if (!self::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
View
343 library/Zend/Crypt/Key/Derivation/Scrypt.php
@@ -0,0 +1,343 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Crypt
+ */
+
+namespace Zend\Crypt\Key\Derivation;
+
+use Zend\Crypt\Key\Derivation\Pbkdf2;
+
+/**
+ * Scrypt key derivation function
+ *
+ * @category Zend
+ * @package Zend_Crypt
+ * @see http://www.tarsnap.com/scrypt.html
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
+ */
+class Scrypt
+{
+ /**
+ * Execute the scrypt algorithm
+ *
+ * @param string $password
+ * @param string $salt
+ * @param integer $n CPU cost
+ * @param integer $r Memory cost
+ * @param integer $p parallelization cost
+ * @param integer $length size of the output key
+ * @return string
+ */
+ public static function calc($password, $salt, $n, $r, $p, $length)
+ {
+ if ($n == 0 || ($n & ($n - 1)) != 0) {
+ throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2");
+ }
+ if ($n > PHP_INT_MAX / 128 / $r) {
+ throw new Exception\InvalidArgumentException("Parameter n is too large");
+ }
+ if ($r > PHP_INT_MAX / 128 / $p) {
+ throw new Exception\InvalidArgumentException("Parameter r is too large");
+ }
+
+ if (extension_loaded('Scrypt')) {
+ if ($length < 16) {
+ throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16");
+ }
+ return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length));
+ }
+
+ $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r);
+
+ $s = '';
+ for ($i = 0; $i < $p; $i++) {
+ $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r);
+ }
+
+ return Pbkdf2::calc('sha256', $password, $s, 1, $length);
+ }
+
+ /**
+ * scryptROMix
+ *
+ * @param string $b
+ * @param integer $n
+ * @param integer $r
+ * @return string
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
+ */
+ protected static function scryptROMix($b, $n, $r)
+ {
+ $x = $b;
+ $v = array();
+ for ($i = 0; $i < $n; $i++) {
+ $v[$i] = $x;
+ $x = self::scryptBlockMix($x, $r);
+ }
+ for ($i = 0; $i < $n; $i++) {
+ $j = self::integerify($x) % $n;
+ $t = $x ^ $v[$j];
+ $x = self::scryptBlockMix($t, $r);
+ }
+ return $x;
+ }
+
+ /**
+ * scryptBlockMix
+ *
+ * @param string $b
+ * @param integer $r
+ * @return string
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-3
+ */
+ protected static function scryptBlockMix($b, $r)
+ {
+ $x = substr($b, -64);
+ $even = '';
+ $odd = '';
+ $len = 2 * $r;
+
+ for ($i = 0; $i < $len; $i++) {
+ if (PHP_INT_SIZE === 4) {
+ $x = self::salsa208Core32($x ^ substr($b, 64 * $i, 64));
+ } else {
+ $x = self::salsa208Core64($x ^ substr($b, 64 * $i, 64));
+ }
+ if ($i % 2 == 0) {
+ $even .= $x;
+ } else {
+ $odd .= $x;
+ }
+ }
+ return $even . $odd;
+ }
+
+ /**
+ * Salsa 20/8 core (32 bit version)
+ *
+ * @param string $b
+ * @return string
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
+ * @see http://cr.yp.to/salsa20.html
+ */
+ protected static function salsa208Core32($b)
+ {
+ $b32 = array();
+ for ($i = 0; $i < 16; $i++) {
+ list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4));
+ }
+
+ $x = $b32;
+ for ($i = 0; $i < 8; $i += 2) {
+ $a = ($x[ 0] + $x[12]);
+ $x[ 4] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[ 4] + $x[ 0]);
+ $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 8] + $x[ 4]);
+ $x[12] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[12] + $x[ 8]);
+ $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[ 5] + $x[ 1]);
+ $x[ 9] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[ 9] + $x[ 5]);
+ $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[13] + $x[ 9]);
+ $x[ 1] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[ 1] + $x[13]);
+ $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[10] + $x[ 6]);
+ $x[14] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[14] + $x[10]);
+ $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 2] + $x[14]);
+ $x[ 6] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[ 6] + $x[ 2]);
+ $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[15] + $x[11]);
+ $x[ 3] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[ 3] + $x[15]);
+ $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 7] + $x[ 3]);
+ $x[11] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[11] + $x[ 7]);
+ $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[ 0] + $x[ 3]);
+ $x[ 1] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[ 1] + $x[ 0]);
+ $x[ 2] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 2] + $x[ 1]);
+ $x[ 3] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[ 3] + $x[ 2]);
+ $x[ 0] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[ 5] + $x[ 4]);
+ $x[ 6] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[ 6] + $x[ 5]);
+ $x[ 7] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 7] + $x[ 6]);
+ $x[ 4] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[ 4] + $x[ 7]);
+ $x[ 5] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[10] + $x[ 9]);
+ $x[11] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[11] + $x[10]);
+ $x[ 8] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[ 8] + $x[11]);
+ $x[ 9] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[ 9] + $x[ 8]);
+ $x[10] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ $a = ($x[15] + $x[14]);
+ $x[12] ^= ($a << 7) | ($a >> 25) & 0x7f;
+ $a = ($x[12] + $x[15]);
+ $x[13] ^= ($a << 9) | ($a >> 23) & 0x1ff;
+ $a = ($x[13] + $x[12]);
+ $x[14] ^= ($a << 13) | ($a >> 19) & 0x1fff;
+ $a = ($x[14] + $x[13]);
+ $x[15] ^= ($a << 18) | ($a >> 14) & 0x3ffff;
+ }
+ for ($i = 0; $i < 16; $i++) {
+ $b32[$i] = $b32[$i] + $x[$i];
+ }
+ $result = '';
+ for ($i = 0; $i < 16; $i++) {
+ $result .= pack("V", $b32[$i]);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Salsa 20/8 core (64 bit version)
+ *
+ * @param string $b
+ * @return string
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-2
+ * @see http://cr.yp.to/salsa20.html
+ */
+ protected static function salsa208Core64($b)
+ {
+ $b32 = array();
+ for ($i = 0; $i < 16; $i++) {
+ list(, $b32[$i]) = unpack("V", substr($b, $i * 4, 4));
+ }
+
+ $x = $b32;
+ for ($i = 0; $i < 8; $i += 2) {
+ $a = ($x[ 0] + $x[12]) & 0xffffffff;
+ $x[ 4] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[ 4] + $x[ 0]) & 0xffffffff;
+ $x[ 8] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 8] + $x[ 4]) & 0xffffffff;
+ $x[12] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[12] + $x[ 8]) & 0xffffffff;
+ $x[ 0] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[ 5] + $x[ 1]) & 0xffffffff;
+ $x[ 9] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[ 9] + $x[ 5]) & 0xffffffff;
+ $x[13] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[13] + $x[ 9]) & 0xffffffff;
+ $x[ 1] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[ 1] + $x[13]) & 0xffffffff;
+ $x[ 5] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[10] + $x[ 6]) & 0xffffffff;
+ $x[14] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[14] + $x[10]) & 0xffffffff;
+ $x[ 2] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 2] + $x[14]) & 0xffffffff;
+ $x[ 6] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[ 6] + $x[ 2]) & 0xffffffff;
+ $x[10] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[15] + $x[11]) & 0xffffffff;
+ $x[ 3] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[ 3] + $x[15]) & 0xffffffff;
+ $x[ 7] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 7] + $x[ 3]) & 0xffffffff;
+ $x[11] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[11] + $x[ 7]) & 0xffffffff;
+ $x[15] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[ 0] + $x[ 3]) & 0xffffffff;
+ $x[ 1] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[ 1] + $x[ 0]) & 0xffffffff;
+ $x[ 2] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 2] + $x[ 1]) & 0xffffffff;
+ $x[ 3] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[ 3] + $x[ 2]) & 0xffffffff;
+ $x[ 0] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[ 5] + $x[ 4]) & 0xffffffff;
+ $x[ 6] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[ 6] + $x[ 5]) & 0xffffffff;
+ $x[ 7] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 7] + $x[ 6]) & 0xffffffff;
+ $x[ 4] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[ 4] + $x[ 7]) & 0xffffffff;
+ $x[ 5] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[10] + $x[ 9]) & 0xffffffff;
+ $x[11] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[11] + $x[10]) & 0xffffffff;
+ $x[ 8] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[ 8] + $x[11]) & 0xffffffff;
+ $x[ 9] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[ 9] + $x[ 8]) & 0xffffffff;
+ $x[10] ^= ($a << 18) | ($a >> 14);
+ $a = ($x[15] + $x[14]) & 0xffffffff;
+ $x[12] ^= ($a << 7) | ($a >> 25);
+ $a = ($x[12] + $x[15]) & 0xffffffff;
+ $x[13] ^= ($a << 9) | ($a >> 23);
+ $a = ($x[13] + $x[12]) & 0xffffffff;
+ $x[14] ^= ($a << 13) | ($a >> 19);
+ $a = ($x[14] + $x[13]) & 0xffffffff;
+ $x[15] ^= ($a << 18) | ($a >> 14);
+ }
+ for ($i = 0; $i < 16; $i++) {
+ $b32[$i] = ($b32[$i] + $x[$i]) & 0xffffffff;
+ }
+ $result = '';
+ for ($i = 0; $i < 16; $i++) {
+ $result .= pack("V", $b32[$i]);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Integerify
+ *
+ * Integerify (B[0] ... B[2 * r - 1]) is defined as the result
+ * of interpreting B[2 * r - 1] as a little-endian integer.
+ * Each block B is a string of 64 bytes.
+ *
+ * @param string $b
+ * @return integer
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-4
+ */
+ protected static function integerify($b) {
+ $v = 'v';
+ if (PHP_INT_SIZE === 8) {
+ $v = 'V';
+ }
+ list(,$n) = unpack($v, substr($b, -64));
+ return $n;
+ }
+
+ /**
+ * Convert hex string in a binary string
+ *
+ * @param string $hex
+ * @return string
+ */
+ protected static function hex2bin($hex) {
+ if (version_compare(PHP_VERSION, '5.4') >= 0) {
+ return hex2bin($hex);
+ }
+ $len = strlen($hex);
+ $result = '';
+ for ($i = 0; $i < $len; $i+=2) {
+ $result .= chr(hexdec($hex[$i] . $hex[$i+1]));
+ }
+ return $result;
+ }
+}
View
7 tests/ZendTest/Crypt/HmacTest.php
@@ -200,13 +200,6 @@ public function testHmacRIPEMD160_7()
$this->assertEquals('69ea60798d71616cce5fd0871e23754cd75d5a0a', $hmac);
}
- public function testEmptyKey()
- {
- $this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException',
- 'Provided key is null or empty');
- $hash = HMAC::compute(null, 'md5', 'test');
- }
-
public function testWrongHashAlgorithm()
{
$this->setExpectedException('Zend\Crypt\Exception\InvalidArgumentException',
View
195 tests/ZendTest/Crypt/Key/Derivation/ScryptTest.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Crypt
+ */
+
+namespace ZendTest\Crypt\Key\Derivation;
+
+use Zend\Crypt\Key\Derivation\Scrypt;
+
+/**
+ * @category Zend
+ * @package Zend_Crypt
+ * @subpackage UnitTests
+ * @group Zend_Crypt
+ */
+class ScryptTest extends \PHPUnit_Framework_TestCase
+{
+
+ protected static function getMethod($name) {
+ $class = new \ReflectionClass('Zend\Crypt\Key\Derivation\Scrypt');
+ $method = $class->getMethod($name);
+ $method->setAccessible(true);
+ return $method;
+ }
+
+ /**
+ * Test vector of Salsa 20/8 core
+ *
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-7
+ */
+ public function testVectorSalsa208Core()
+ {
+ $hexInput = '7e 87 9a 21 4f 3e c9 86 7c a9 40 e6 41 71 8f 26
+ ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d
+ ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32
+ 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e';
+
+ $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05
+ 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29
+ b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba
+ e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81';
+
+
+ $salsaAlg = 'salsa208Core32';
+ if (PHP_INT_SIZE === 8) {
+ $salsaAlg = 'salsa208Core64';
+ }
+ $salsa20 = self::getMethod($salsaAlg);
+ $obj = new Scrypt;
+ $input = self::hex2bin(str_replace(array(' ',"\n"),'',$hexInput));
+ $result = $salsa20->invokeArgs($obj, array($input));
+
+ $this->assertEquals(64, strlen($input), 'Input must be a string of 64 bytes');
+ $this->assertEquals(64, strlen($result), 'Output must be a string of 64 bytes');
+ $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result));
+ }
+ /**
+ * Test vector of Scrypt BlockMix
+ *
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-8
+ */
+ public function testVectorScryptBlockMix()
+ {
+ $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd
+ 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad
+ 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29
+ 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7
+
+ 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb
+ cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0
+ 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b
+ 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89';
+
+ $hexOutput = 'a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05
+ 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29
+ b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba
+ e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81
+
+ 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c
+ 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7
+ 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6
+ 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25';
+
+ $blockMix = self::getMethod('scryptBlockMix');
+ $obj = new Scrypt;
+ $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput));
+ $result = $blockMix->invokeArgs($obj, array($input, 1));
+
+ $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result));
+ }
+
+ /**
+ * Test vector of Scrypt ROMix
+ *
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-9
+ */
+ public function testVectorScryptROMix()
+ {
+ $hexInput = 'f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd
+ 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad
+ 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29
+ 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7
+ 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb
+ cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0
+ 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b
+ 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89';
+
+ $hexOutput = '79 cc c1 93 62 9d eb ca 04 7f 0b 70 60 4b f6 b6
+ 2c e3 dd 4a 96 26 e3 55 fa fc 61 98 e6 ea 2b 46
+ d5 84 13 67 3b 99 b0 29 d6 65 c3 57 60 1f b4 26
+ a0 b2 f4 bb a2 00 ee 9f 0a 43 d1 9b 57 1a 9c 71
+ ef 11 42 e6 5d 5a 26 6f dd ca 83 2c e5 9f aa 7c
+ ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4
+ ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f
+ 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e';
+
+
+ $roMix = self::getMethod('scryptROMix');
+ $obj = new Scrypt;
+ $input = self::hex2bin(str_replace(array(' ',"\n"), '', $hexInput));
+ $result = $roMix->invokeArgs($obj, array($input, 16, 1));
+
+ $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result));
+ }
+
+
+ /**
+ * Test Vector Scrypt
+ *
+ * @see https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01#section-11
+ */
+ public function testVectorScrypt()
+ {
+ $hexOutput = '77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97
+ f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42
+ fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17
+ e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06';
+
+ $result = Scrypt::calc('', '', 16, 1, 1, 64);
+ $this->assertEquals(64, strlen($result));
+ $this->assertEquals(str_replace(array(' ',"\n"),'',$hexOutput), bin2hex($result));
+ }
+
+ /**
+ * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException
+ */
+ public function testScryptWrongN()
+ {
+ $result = Scrypt::calc('test', 'salt', 17, 1, 1, 64);
+ $result = Scrypt::calc('test', 'salt', PHP_INT_MAX, 1, 1, 64);
+ }
+
+ /**
+ * @expectedException Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException
+ */
+ public function testScryptWrongR()
+ {
+ $result = Scrypt::calc('test', 'salt', PHP_INT_MAX / 128, 4, 1, 64);
+ }
+
+ /**
+ * Test scrypt correct size output
+ */
+ public function testScryptSize()
+ {
+ for ($size = 0; $size < 64; $size++) {
+ if (extension_loaded('Scrypt') && ($size < 16)) {
+ $this->setExpectedException('Zend\Crypt\Key\Derivation\Exception\InvalidArgumentException');
+ }
+ $result = Scrypt::calc('test', 'salt', 16, 1, 1, $size);
+ $this->assertEquals($size, strlen($result));
+ }
+ }
+
+ /**
+ * Convert a string with hex values in binary string
+ *
+ * @param string $hex
+ * @return string
+ */
+ protected static function hex2bin($hex)
+ {
+ $len = strlen($hex);
+ $result = '';
+ for ($i = 0; $i < $len; $i += 2) {
+ $result .= chr(hexdec($hex[$i] . $hex[$i+1]));
+ }
+ return $result;
+ }
+}

0 comments on commit 19c78a5

Please sign in to comment.
Something went wrong with that request. Please try again.