Cryptography in Zend Framework 2 Enrico Zimuel Senior PHP Engineer Zend Framework Team Zend Technologies Uncon – 9th June, Dutch PHP Conference 2012
ZendCrypt ● ZendCrypt is a new component of ZF2 (>= 2.0.0beta4) ● Facilitates the usage of cryptography in PHP projects ● Supports strong cryptography (standards + best practices)
ZendCrypt: main features ● Symmetric encryption/decryption + authentication ● Public key cryptography ● Key Derivation Function (PBKDF2, Salted2SK) ● Secure password hashing (bcrypt) ● Hash ● Hash-based Message Authentication Code (HMAC)
Supported algorithms ● Mcrypt: AES (Rijndael-128), Rijndael-192/256, Blowfish, Twofish, DES, 3DES, CAST-128/256, Saferplus, Serpent, ● OpenSSL: RSA, Diffie Hellman ● PBKDF2, Salted2SK ● Bcrypt ● Hash/HMAC functions provided by PHP: MD5, SHA- 1/224/256/384/512, RIPEMD, TIGER, AVAL, ...
ZendCrypt components ● ZendCryptSymmetricMcrypt ● ZendCryptPublicKeyRsa ● ZendCryptPublicKeyDiffieHellman ● ZendCryptPassword ● ZendCryptKeyDerivation ● ZendCryptBlockCipher ● ZendCryptHash ● ZendCryptHmac
Encryption + authentication ● ZendCryptBlockCipher ● Default: – AES encryption in CBC mode – HMAC authentication (SHA-256) – Random IV for each encryption – PKCS7 padding (RFC 5652) – PBKDF2 for key derivation (encrypt and auth) – Prevent timing attacks
Example: encrypt/decrypt use ZendCryptBlockCipher; use ZendCryptBlockCipher;     $cipher = BlockCipher::factory('mcrypt', $cipher = BlockCipher::factory('mcrypt', array('algorithm' => 'aes') array('algorithm' => 'aes') ); ); $cipher->setKey('this is the encryption key'); $cipher->setKey('this is the encryption key'); $text $text = 'This is the message to encrypt'; = 'This is the message to encrypt'; $encrypted = $cipher->encrypt($text); $encrypted = $cipher->encrypt($text);     printf("Encrypted text: %sn", $encrypted); printf("Encrypted text: %sn", $encrypted); $text $text = $cipher->decrypt($encrypted); = $cipher->decrypt($encrypted); printf("Decrypted text: %sn", $text); printf("Decrypted text: %sn", $text);
Encryption format Encryption = HMAC . IV . ENCRYPT ● MSG is the message to encrypt ● KEY is the encryption key (by PBKDF2) ● AUTH is the authentication key (by PBKDF2) ● ENCRYPT = AES(MSG, KEY) ● HMAC = HMAC('sha256', AUTH, 'AES' . IV . ENCRYPT) ● IV = random
How to store a password? ● “More than 6 million LinkedIn passwords stolen” 7th July 2012, cnnmoney.com ● Don't use only an hash algorithm (dictionary attacks) ● Even using a salt is insecure (brute force attacks)
How to safely store a password ● bcrypt is an adaptive cryptographic hash function for passwords ● It's considered secure because is slow (prevent dictionary attacks) ● Implemented using crypt() of PHP ● It uses a parameter, the workload (or cost) that specify the amount of work ● More work means more secure hash value
Example: usage of bcrypt use ZendCryptPasswordBcrypt; use ZendCryptPasswordBcrypt;     $bcrypt $bcrypt = new Bcrypt(); = new Bcrypt(); $password = $bcrypt->create('password'); $password = $bcrypt->create('password'); printf ("Password: %sn", $password); printf ("Password: %sn", $password); ● The output ($password) is a string of 60 bytes ● The default value of the working factor is 14
The bcrypt workload
Check for valid passwords use ZendCryptPasswordBcrypt; use ZendCryptPasswordBcrypt;     $bcrypt $bcrypt = new Bcrypt(); = new Bcrypt(); $password = $_POST['password']; $password = $_POST['password']; $hash $hash = '…'; // i.e. get from a database = '…'; // i.e. get from a database if ($bcrypt->verify($password, $hash)) { if ($bcrypt->verify($password, $hash)) { echo “The password is valid”; echo “The password is valid”; } else { } else { Echo “The password is not valid”; Echo “The password is not valid”; } }
Key Derivation Function ● NEVER USE user's password as crypto key! ● Key Derivation Function generates cryptographic keys based on user's passwords ● PBKDF2 is a KDF (RFC 2898, PKCS #5 v2.0)
PBKDF2 “PBKDF2 applies a pseudorandom function, such as a cryptographic hash, cipher, or HMAC to the input password or passphrase along with a salt value and repeats the process many times to produce a derived key, which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult, and is known as key stretching” From Wikipedia
Example: Pbkdf2 use ZendCryptKeyDerivationPbkdf2, use ZendCryptKeyDerivationPbkdf2, ZendMathMath; ZendMathMath;     $salt = Math::randBytes(32); $salt = Math::randBytes(32); $pass = 'this is the password of the user'; $pass = 'this is the password of the user'; $hash = Pbkdf2::calc('sha256', $pass, $salt, 10000, 32); $hash = Pbkdf2::calc('sha256', $pass, $salt, 10000, 32); ● It generates a crypto key of 32 bytes using SHA-256 + random salt with an interation of 10'000 times
How many iterations we need? ● It depends on the CPU power that you use ● Suggestion: use at least 1 sec. of computation ● Using an Intel Core i5 CPU at 3.3Ghz you need at least 100’000 iterations to get about 1 sec. of computation
ZF2 random number generator ● ZendMathMath::randBytes($length, $strong = false) ● ZendMathMath::rand($min, $max, $strong = false) ● Fallback strategy: 1) If OpenSSL: openssl_random_pseudo_bytes() 2) If Mcrypt: mcrypt_create_iv() 3) If (!$strong): mt_rand() 4) else throwing exception “Cannot generate strong random numbers”
Some references ● Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno “ Cryptography Engineering” John Wiley & Sons, 2010 ● Dan Boneh, Cryptography Course, Stanford University, Coursera free online courses ● Coda Hale, How to safely store a password ● Zend Framework 2 ● Anthony Ferrara, PHP-CryptLib ● E.Zimuel “Cryptography in PHP” Web & PHP Magazine, Issue 2/2012 ● E.Zimuel “Cryptography made easy with Zend Framework”
Thanks! ● Contacts: enrico@zend.com @ezimuel

Cryptography with Zend Framework

  • 1.
    Cryptography in ZendFramework 2 Enrico Zimuel Senior PHP Engineer Zend Framework Team Zend Technologies Uncon – 9th June, Dutch PHP Conference 2012
  • 2.
    ZendCrypt ● ZendCrypt is a new component of ZF2 (>= 2.0.0beta4) ● Facilitates the usage of cryptography in PHP projects ● Supports strong cryptography (standards + best practices)
  • 3.
    ZendCrypt: main features ● Symmetric encryption/decryption + authentication ● Public key cryptography ● Key Derivation Function (PBKDF2, Salted2SK) ● Secure password hashing (bcrypt) ● Hash ● Hash-based Message Authentication Code (HMAC)
  • 4.
    Supported algorithms ● Mcrypt: AES (Rijndael-128), Rijndael-192/256, Blowfish, Twofish, DES, 3DES, CAST-128/256, Saferplus, Serpent, ● OpenSSL: RSA, Diffie Hellman ● PBKDF2, Salted2SK ● Bcrypt ● Hash/HMAC functions provided by PHP: MD5, SHA- 1/224/256/384/512, RIPEMD, TIGER, AVAL, ...
  • 5.
    ZendCrypt components ● ZendCryptSymmetricMcrypt ● ZendCryptPublicKeyRsa ● ZendCryptPublicKeyDiffieHellman ● ZendCryptPassword ● ZendCryptKeyDerivation ● ZendCryptBlockCipher ● ZendCryptHash ● ZendCryptHmac
  • 6.
    Encryption + authentication ● ZendCryptBlockCipher ● Default: – AES encryption in CBC mode – HMAC authentication (SHA-256) – Random IV for each encryption – PKCS7 padding (RFC 5652) – PBKDF2 for key derivation (encrypt and auth) – Prevent timing attacks
  • 7.
    Example: encrypt/decrypt use ZendCryptBlockCipher; useZendCryptBlockCipher;     $cipher = BlockCipher::factory('mcrypt', $cipher = BlockCipher::factory('mcrypt', array('algorithm' => 'aes') array('algorithm' => 'aes') ); ); $cipher->setKey('this is the encryption key'); $cipher->setKey('this is the encryption key'); $text $text = 'This is the message to encrypt'; = 'This is the message to encrypt'; $encrypted = $cipher->encrypt($text); $encrypted = $cipher->encrypt($text);     printf("Encrypted text: %sn", $encrypted); printf("Encrypted text: %sn", $encrypted); $text $text = $cipher->decrypt($encrypted); = $cipher->decrypt($encrypted); printf("Decrypted text: %sn", $text); printf("Decrypted text: %sn", $text);
  • 8.
    Encryption format Encryption = HMAC . IV . ENCRYPT ● MSG is the message to encrypt ● KEY is the encryption key (by PBKDF2) ● AUTH is the authentication key (by PBKDF2) ● ENCRYPT = AES(MSG, KEY) ● HMAC = HMAC('sha256', AUTH, 'AES' . IV . ENCRYPT) ● IV = random
  • 9.
    How to storea password? ● “More than 6 million LinkedIn passwords stolen” 7th July 2012, cnnmoney.com ● Don't use only an hash algorithm (dictionary attacks) ● Even using a salt is insecure (brute force attacks)
  • 10.
    How to safelystore a password ● bcrypt is an adaptive cryptographic hash function for passwords ● It's considered secure because is slow (prevent dictionary attacks) ● Implemented using crypt() of PHP ● It uses a parameter, the workload (or cost) that specify the amount of work ● More work means more secure hash value
  • 11.
    Example: usage ofbcrypt use ZendCryptPasswordBcrypt; use ZendCryptPasswordBcrypt;     $bcrypt $bcrypt = new Bcrypt(); = new Bcrypt(); $password = $bcrypt->create('password'); $password = $bcrypt->create('password'); printf ("Password: %sn", $password); printf ("Password: %sn", $password); ● The output ($password) is a string of 60 bytes ● The default value of the working factor is 14
  • 12.
  • 13.
    Check for validpasswords use ZendCryptPasswordBcrypt; use ZendCryptPasswordBcrypt;     $bcrypt $bcrypt = new Bcrypt(); = new Bcrypt(); $password = $_POST['password']; $password = $_POST['password']; $hash $hash = '…'; // i.e. get from a database = '…'; // i.e. get from a database if ($bcrypt->verify($password, $hash)) { if ($bcrypt->verify($password, $hash)) { echo “The password is valid”; echo “The password is valid”; } else { } else { Echo “The password is not valid”; Echo “The password is not valid”; } }
  • 14.
    Key Derivation Function ● NEVER USE user's password as crypto key! ● Key Derivation Function generates cryptographic keys based on user's passwords ● PBKDF2 is a KDF (RFC 2898, PKCS #5 v2.0)
  • 15.
    PBKDF2 “PBKDF2applies a pseudorandom function, such as a cryptographic hash, cipher, or HMAC to the input password or passphrase along with a salt value and repeats the process many times to produce a derived key, which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult, and is known as key stretching” From Wikipedia
  • 16.
    Example: Pbkdf2 use ZendCryptKeyDerivationPbkdf2, useZendCryptKeyDerivationPbkdf2, ZendMathMath; ZendMathMath;     $salt = Math::randBytes(32); $salt = Math::randBytes(32); $pass = 'this is the password of the user'; $pass = 'this is the password of the user'; $hash = Pbkdf2::calc('sha256', $pass, $salt, 10000, 32); $hash = Pbkdf2::calc('sha256', $pass, $salt, 10000, 32); ● It generates a crypto key of 32 bytes using SHA-256 + random salt with an interation of 10'000 times
  • 17.
    How many iterationswe need? ● It depends on the CPU power that you use ● Suggestion: use at least 1 sec. of computation ● Using an Intel Core i5 CPU at 3.3Ghz you need at least 100’000 iterations to get about 1 sec. of computation
  • 18.
    ZF2 random numbergenerator ● ZendMathMath::randBytes($length, $strong = false) ● ZendMathMath::rand($min, $max, $strong = false) ● Fallback strategy: 1) If OpenSSL: openssl_random_pseudo_bytes() 2) If Mcrypt: mcrypt_create_iv() 3) If (!$strong): mt_rand() 4) else throwing exception “Cannot generate strong random numbers”
  • 19.
    Some references ● Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno “ Cryptography Engineering” John Wiley & Sons, 2010 ● Dan Boneh, Cryptography Course, Stanford University, Coursera free online courses ● Coda Hale, How to safely store a password ● Zend Framework 2 ● Anthony Ferrara, PHP-CryptLib ● E.Zimuel “Cryptography in PHP” Web & PHP Magazine, Issue 2/2012 ● E.Zimuel “Cryptography made easy with Zend Framework”
  • 20.
    Thanks! ● Contacts: enrico@zend.com @ezimuel