Skip to content

Commit

Permalink
Add libsodium as a random number source
Browse files Browse the repository at this point in the history
  • Loading branch information
ramsey committed Feb 17, 2016
1 parent 7926752 commit 0690f23
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
82 changes: 82 additions & 0 deletions lib/RandomLib/Source/Sodium.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* The libsodium Random Number Source
*
* This uses the libsodium secure generator to generate high strength numbers
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Ben Ramsey <ben@benramsey.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version Build @@version@@
* @link https://paragonie.com/book/pecl-libsodium
* @link http://pecl.php.net/package/libsodium
*/

namespace RandomLib\Source;

use SecurityLib\Strength;

/**
* The libsodium Random Number Source
*
* This uses the libsodium secure generator to generate high strength numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Ben Ramsey <ben@benramsey.com>
*/
class Sodium implements \RandomLib\Source {

/**
* A property that may be forcibly set to `false` in the constructor, for
* the purpose of testing this source
*
* @var bool
*/
private $hasLibsodium = false;

/**
* Constructs a libsodium Random Number Source
*
* @param bool $useLibsodium May be set to `false` to disable libsodium for
* testing purposes
*/
public function __construct($useLibsodium = true) {
if ($useLibsodium && extension_loaded('libsodium')) {
$this->hasLibsodium = true;
}
}

/**
* Return an instance of Strength indicating the strength of the source
*
* @return Strength An instance of one of the strength classes
*/
public static function getStrength() {
return new Strength(Strength::HIGH);
}

/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size) {
if (!$this->hasLibsodium || $size < 1) {
return str_repeat(chr(0), $size);
}

return \Sodium\randombytes_buf($size);
}

}
68 changes: 68 additions & 0 deletions test/Unit/RandomLib/Source/SodiumTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace RandomLib\Source;

use SecurityLib\Strength;


class SodiumTest extends \PHPUnit_Framework_TestCase {

public static function provideGenerate() {
$data = array();
for ($i = 1; $i < 100; $i += 5) {
$not = str_repeat(chr(0), $i);
$data[] = array($i, $not);
}
return $data;
}

/**
*/
public function testGetStrength() {
$strength = new Strength(Strength::HIGH);
$actual = Sodium::getStrength();
$this->assertEquals($actual, $strength);
}

/**
* @dataProvider provideGenerate
*/
public function testGenerate($length, $not) {
if (!extension_loaded('libsodium')) {
$this->markTestSkipped('The libsodium extension is not loaded');
}

$rand = new Sodium;
$stub = $rand->generate($length);
$this->assertEquals($length, strlen($stub));
$this->assertNotEquals($not, $stub);
}

/**
* @dataProvider provideGenerate
*/
public function testGenerateWithoutLibsodium($length, $not) {
$rand = new Sodium(false);
$stub = $rand->generate($length);
$this->assertEquals($length, strlen($stub));
$this->assertEquals($not, $stub);
}

public function testGenerateWithZeroLength() {
if (!extension_loaded('libsodium')) {
$this->markTestSkipped('The libsodium extension is not loaded');
}

$rand = new Sodium;
$stub = $rand->generate(0);
$this->assertEquals(0, strlen($stub));
$this->assertEquals('', $stub);
}

public function testGenerateWithZeroLengthWithoutLibsodium() {
$rand = new Sodium(false);
$stub = $rand->generate(0);
$this->assertEquals(0, strlen($stub));
$this->assertEquals('', $stub);
}
}

0 comments on commit 0690f23

Please sign in to comment.