Skip to end of metadata
Go to start of metadata

<p>Following on from this <a href="">mailing list discussion</a>, and <a href="">IRC meeting of 28th March</a> this RFC describes the new features to add to the Zend\Crypt component.</p>

<p>The idea is to improve the Zend\Crypt with some new API to provide a simple way to encrypt/decrypt sensitive information and to store password in a secure way using the <a href="">bcrypt</a> algorithm. For the encryption/decryption API the idea is to use one of the MCrypt <a href="">simmetric algorithms</a> in <a href="">CBC mode</a> and authenticate the encrypted data using <a href="">encrypt-then-authenticate</a> schema. The CBC mode for simmetric ciphers with the usage of random <a href="">IV</a> and the encrypt-then-authenticate schema is considered secure from the community of cryptographic engineers (in primis <a href="">Bruce Schneier</a> that suggests this use case in the books <a href="">Cryptopgraphy Engineering</a>). <br />
For the authentication schema the idea is to use the Zend\Crypt\Hmac::compute() function with the <a href="">SHA-256</a> algorithm. If you are wondering why we have to authenticate an encrypted message you should read the article of Serge Vaudenay about the <a href="">Padding oracle attack</a>.<br />
For more information on the security of encrypt-then-authenticate schema you can read the article <a href="">The order of encryption and authentication for protecting communications (Or: how secure is SSL?)</a> of Hugo Krawczyk.</p>

<p>The idea is to offer a generic API to encrypt/decrypt string (to add to the Zend\Crypt class):</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public static function encrypt(string $data, string $key, string $alg = 'rijndael-128', string $iv = null) {}
public static function decrypt(string $data, string $key) {}

<p>where $alg is the cipher algorithm (<a href="">AES</a> by default: rijndael-128), and $iv is the Initialization Vector (IV).<br />
Note: the decrypt function does not need the cipher algorithm and the IV specification because they are stored in the encrypted string.</p>

<p>And we want to support the encryption/decryption of Stream (for instance a file) using the following API:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public static function encryptStream(string $data, string $key, resource $stream, string $alg = 'rijndael-128', string $iv = null) {}
public static function decryptStream(string $data, string $key, resource $stream) {}

<h2>Bcrypt support</h2>

<p>I would like to add a better interface of the algorithm bcrypt that is supported by PHP 5.3.0+. The API for the bcrypt algorithm is supported in the crypt() function.<br />
In order to use the bcrypt you have to use a syntax like that:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$salt = substr(str_replace('+', '.',base64_encode($salt)), 0, 22);
$hash = crypt($password,'$2a$'.$workload.'$'.$salt);

<p>The bcrypt algorithm is recognized as the best algorithm for storing user's passwords. You can read this interesting article <a href="">How To Safely Store A Password</a> of Coda Hale to discover why.<br />
The idea is to add the bcrypt algorithm as static function in Zend\Crypt. </p>

<p>The $workload factor is related to the CPU speed (it is a number from 10 to 31). To estimate the value to use as $workload factor you can refer to the slides num. 17 of my presentation at <a href="">ZendCon</a> 2011, <a href="">Cryptography in PHP: use cases</a>.</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public static function bcrypt(string $data, string $salt = null, int $workload = 14) {}

<h2>Improve the randomness of rand() in Zend\Crypt\Math</h2>

<p>I would like to refactor the Zend\Crypt\Math::rand to use the openssl_random_pseudo_bytes as first option and after the /dev/urandom source.</p>

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Mar 29, 2012

    <p>Hi Enrico, thanks for writing this down.</p>

    <p>First of all you know my opinion about Math already, I'd rather refactor any math related stuff to a Math namespace.</p>

    <p>About the encrypt and decrypt functions. Wouldn't it make more sense to have an Encrypter object? That way one can create their own encryption algorithms. Something like:</p>

    <ac:macro ac:name="code"><ac:parameter ac:name="title">Example</ac:parameter><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:plain-text-body><![CDATA[
    interface Encrpyter
    public function decrypt( $data );
    public function decryptStream( $stream );

    public function encrypt( $data );
    public function encryptStream( $data );

    class Rijndael128Encrypter implements Encrpyter
    // ...

    class MyCustomEncrypter implements Encrpyter
    // ...

    class MyWorker
    private $_encrypter;

    public function __construct( $encrypter )

    Unknown macro: { $this->_encrypter = $encrypter; }

    public function load( $path )

    Unknown macro: { $data = $this->_readData( $path ); $data = $this->_encrypter->decrypt( $data ); // ... }

    public function save( $path )

    Unknown macro: { $data = $this->_writeData(); $data = $this->_encrypter->encrypt( $data ); // ... }


    $worker = new MyWorker( new MyCustomEncrypter() );
    $worker->save( 'test' );

    <p>Or am I missing the point here?</p>

  2. Mar 29, 2012

    <p>Hi Walter,<br />
    as developer I like the idea to have an Encryption interface but at the same time I don't want to encourage PHP developers to customize the encryption/decryption algorithms. The cryptography algorithms must be standard and that's why I mentioned the Mcrypt extension in the RFC. If we are going to use only the MCrypt actually I don't think we need an Encryption interface for that. The idea to implement cryptographic algorithms in PHP doesn't sound good to me for a security reason and last, but not least, for the performance.</p>