View Source

<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>