Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="note"><ac:parameter ac:name="title">Updated</ac:parameter><ac:rich-text-body>
<p>This RFC has been recently updated to the new component structure</p></ac:rich-text-body></ac:macro>

<p>This RFC contains a proposal for implementing cryptographicaly strong pseudo-random number generator (RNG) in ZF2. Several components withing current ZF2 reqire strong random number and there is also a possibility for future user-space modules to use this component. So component will be single point of generating strong pseudo-random numbers.</p>

<p>Working prototype is ready. Please see <a href="https://github.com/denixport/zf2/tree/feature/rand/library/Zend/Math/Rand">this feature branch</a> on GitHub.</p>

<h2>Overview</h2>
<p>RNG uses scheme described in <a href="http://tools.ietf.org/html/rfc4086">RFC 4086</a>. Generator collects inital entropy data from varous sources, adds this data to entropy pool and periodically mixes the pool with some complex mixing function. This way even with weak and predictable sources of entropy, generated random value is cryptographicaly strong. <br />
Component is partly based on TrueCrypt RNG.</p>

<h2>Component Structure</h2>
<h3>Zend\Math\Rand\Generator</h3>
<p>Generator is constructed with array of sources of randomness (<code>SourceInterface</code>) and mixing function (<code>MixerInterface</code>). This is the way to create custom generators with custom set of sources and mixing function. <br />
Methods to get random values are:</p>
<ul>
<li><code>generate($length)</code> – random binary string of <code>$length</code> bytes</li>
<li><code>getBoolean()</code> – boolean</li>
<li><code>getInt($min = 0, $max = PHP_INT_MAX)</code> – int within <code>$min</code> & <code>$max</code></li>
<li><code>getFloat()</code> – floating point number between 0 and 1 with machine's precision</li>
<li><code>getString($length, $charlist)</code> – generates random ASCII string</li>
</ul>

<h3>Factory (Zend\Math\Rand\GeneratorFactory)</h3>
<p>Factory is a fast way to create generator based on pre-defined strength. Generator supports three levels of strength: low, medium, high. For each level different sources and mixing function is used. <br />
Factory methods are:</p>
<ul>
<li><code>create($options)</code> – create instance based on provided options</li>
<li><code>createGenerator($strength = Strength::MEDIUM)</code> – create generator of required strength</li>
</ul>

<h3>Source (Zend\Math\Rand\SourceInterface)</h3>
<p>Different sources of entropy in PHP: openssl, /dev/urandom/, mt_rand() etc. </p>

<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
namespace Zend\Math\Rand\Source;

interface SourceInterface
{
public static function isAvailable();
public static function getStrength();
public function generate($length);
}
]]></ac:plain-text-body></ac:macro>

<h3>Mixer (Zend\Math\Rand\MixerInterface)</h3>
<p>Mixing function. Default mixing function is hash mixer based on SHA-512, RIPEMD, Whirpool</p>

<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
namespace Zend\Math\Rand\Mixer;

interface MixerInterface
{
public static function getStrength();
public function mix($bytes);
}
]]></ac:plain-text-body></ac:macro>

<h2>Questions</h2>
<p>Due to refactoring, some questions are not relevant anymore.</p>

<ul>
<li><em>Should RNG component have it's own namespace Zend\Random or live in Zend\Math, or Zend\Crypt?</em></li>
</ul>

<ul>
<li><span style="text-decoration: line-through;">Should RNG express what kind of algorithm ("cryptographically strong" or week) was used?</span></li>
</ul>

<ul>
<li><span style="text-decoration: line-through;">Should component use adapters or single class is good enough?</span></li>
</ul>

<ul>
<li><span style="text-decoration: line-through;">Should there be a distinction between int/bigint (float/bigfloat)?</span></li>
</ul>

<ul>
<li><span style="text-decoration: line-through;">What other adapters, if any, component should provide?</span></li>
</ul>

<h2>References</h2>
<ul>
<li><a href="http://tools.ietf.org/html/rfc4086">RFC 4086</a></li>
<li><a href="http://www.truecrypt.org/docs/?s=random-number-generator">TrueCrypt RNG</a></li>
</ul>

Labels:
rfc rfc Delete
zf2 zf2 Delete
random random Delete
rng rng Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Apr 10, 2012

    <p>I'm doing the refactor of Zend\Crypt\Math in Zend\Math and i think your Rand component can be part of Zend\Math.<br />
    I think we should provide only random algorithms that are "reasonably strong".<br />
    For instance, I will remove the PhpMtRand from the list of adapters because the Mersenne Twister is not cryptographically strong.<br />
    If a developer doesn't need a strong random number generator can use the standard functions rand() or mt_rand() of PHP. In this way we can also encourage people to use the Zend\Math\Rand component to improve the security of the random values.<br />
    I like the idea to expose an API to generate random boolean, integer, float, binary and string values (maybe we can use a single method to generate strings as a particular bytes value, but this is a detail).<br />
    I think the adapters architecture works fine, in this way we can manage different random generator algorithms.<br />
    There is a very nice PHP project <a href="https://github.com/ircmaxell/PHP-CryptLib">PHP-CryptLib</a> that implements different random numbers generators. <br />
    The idea to provide a secure random number generator for cryptography is to use different random sources. We can think to reuse this approach in our implementation.</p>

    1. Apr 10, 2012

      <p>Thanks for the link, Enrico. I will study it.</p>

      <p>On mt_rand adapter, there is a convinience of getting boolean, float & string from MT when strong random is not needed. So there could be 2 options:<br />
      1) Rand produces only 'reasonably strong' numbers, so no 'weak' adapters<br />
      2) Provide $useStrongRand = true/false option to constructor, true by default<br />
      In both cases, should Rand throw an exception when not strong algo was used (like with openssl extension) ?</p>

      <p>What do you think about separating int/float and bigint/bigfloat?</p>

      <p>UPD: I have reviewed CryptLib, and as far as I understand they consider mt_rand() + mixing as a reasonable way ro obtain strong random number.</p>

      1. Apr 11, 2012

        <p>mt_rand() + mixing is a "quite good technique" for randomness but the key here is the mixing, not the mt_rand(). If we mix any pseudo random source we can improve the quality of randomness, according to the <a href="http://www.ietf.org/rfc/rfc4086.txt">RFC 4086</a>.<br />
        I think we can use strong random generator as default and throw and exception if a user try to use a weak adapter like mt_rand(). We can expose an API, as you proposed, something like setStrongRandom(false), to disable the exception.</p>

  2. Apr 10, 2012

    <p>I like your idea to have a reusable API for random numbers and I also think Zend\Math is the best place for it.</p>

    <table><tbody>
    <tr>
    <td><p> Should there be a distinction between int/bigint (float/bigfloat)?</p></td>
    </tr>
    <tr>
    <td><p> So getInt() will generate numbers within 0 - PHP_INT_MAX, and getBigInt will generate numbers of arbitrary size as strings</p></td>
    </tr>
    </tbody></table>

    <p>The PHP-Float type is a double precision floating point number - What do you mean with big float ?</p>

    1. Apr 10, 2012

      <p>Big float, I mean arbitrary precision beyond PHP's double, something like 9.9e-50</p>

  3. Apr 11, 2012

    <p>I have reviewed CryptoLib. It's very good piece of code, PHP 5.3, PR-0, MIT licence etc. Though I have spotted some silly mistakes in code, so not sure if it was even tested.</p>

    <p>I very much like RFC 4086 compliance aproach of random sources + mixing.<br />
    But it requires block ciphers for medium/strong mixing function. Cipher algorithms blong to Zend\Crypt, so Math\Rand actualy again becomes Crypt\Rand <ac:emoticon ac:name="smile" /> or at least tightly coupled with Zend\Crypt.</p>

    <p>I'd replace cryptolib gradation of strength with just low/medium/high. Or it could be low/medium/high and none. <br />
    Where 'none' means low strength random sources and no mixing or faster xor mixing.</p>