Cryptography ============ In PHP ====== ## For The Average Dev
## Cryptography * Keeping Data Secure * Safe From Viewing * Safe From Tampering * Safe From Forgery * Not A Silver Bullet * XSS * SQLI * Social Engineering * Very Hard To Do * Any bug will cause problems
The First Rule ============== of Cryptography ===============
Don't Do It! ============
Leave It For ============ Experts! ========
## Random! * The foundation of Cryptography * Classified As Three Types: * Weak * For non-cryptographic usages * Strong * For cryptographic usage where security does not depend on the strength of randomness * Cryptographically Secure * For cryptographic usage when security does depend the strength of randomness
## Vulnerabilities of Randomness * Bias * Certain values tend to occur more often making it easier to predict * Predictability * Knowing past numbers helps predict future ones * Poisoning * Ability to alter future random number generation
## Weak Random in PHP * `rand()` * `mt_rand()` * `uniqid()` * `lcg_value()`
## Strong Random in PHP * `mcrypt_create_iv()` * `openssl_random_pseudo_bytes()` * `/dev/urandom` * For *nix systems only
## Cryptographically Secure * `mcrypt_create_iv()` * Maybe: `openssl_random_pseudo_bytes()` * `/dev/random` * For *nix systems only
NEVER Use Weak ============== For Security ============
NEVER Use CS ============ When Not Needed! ================
If In Doubt =========== Use Strong ========== Randomness ==========
## Encryption vs Hashing * Encryption * Encoding * 2 Way / Reversible * Putting a lock on a box * Hashing * Signing * 1 Way / Non-Reversible * Taking a person's finger-print
Encryption ==========
Seriously, ========== Don't Do It! ============
## Two Kinds * Symmetric Encryption * Like a Pad-Lock with shared key * The only secret is the key * Both sides must have same key * Asymmetric Encryption * Like a pair of Pad-Locks * The "lock" is the public-key * The only secret is the private key * Both sides have their own key
## Symmetric Encryption 101 * Number: `01` * Scratch That * Numbers: `01 04 01 54 95 42 64 12`
## Symmetric Ecryption 101 ##Let's Add A "Secret" Number! * `01 04 01 54 95 42 64 12` * `+ 10` * `11 14 11 64 05 52 74 22`
## Symmetric Encryption 101 * We just invented the Caesar Cipher * Commonly known as ROT13 * But There Are Problems: * Vulnerable To Statistical Attacks * Vulnerable To Brute Forcing * Only 100 possible secret numbers!
## I Know! ## Let's add a *different* number * `01 04 01 54 95 42 64 12` * `10 43 21 95 42 67 31 83` * `11 47 22 49 37 09 95 95`
## How It Works * We can generate the pads in two ways * Randomly * If we only use once, perfect security * Known as a one-time-pad * If we use multiple times, same as a caesar cipher * With a function * Given one or two inputs * A key, and an "offset" * Generates a "stream" of pseudo random numbers
## Ciphers * Take 2 inputs * A secret key * An "input" * Produces Pseudo-Random Output * Looks random (statstically) * Is reproducable
## Modes * Multiple ways to use the key stream * Each way is known as a "Mode" * Some are secure * Others are not
## ECB * Electronic Code Book * Uses plain text as "input" * Uses output as ciphertext * VERY BROKEN!!!
## CBC * Cipher Block Chaining * Uses an "Initialization Vector" * Helps "randomize" the plaintext * Ensures no non-unique blocks * Does **NOT** need to be secret! * Chains each block together * Propagating the generated "randomness" * Plain Text Must Be Padded * To a multiple of block-size * Secure!
## CFB * Cipher FeedBack * Uses an "Initialization Vector" * Plain Text never enters cipher * Does not need to be padded * "Decrypt" Is Never Used * Secure!
## Ciphers * AES 128 & 256 * Standard * Also known as RIJNDAEL-128 * Very Strong * Blowfish * TwoFish * Serpent
## Authentication * How do you know it wasn't tampered with? * HMAC * Hash-based Message Authentication Code * USE A SEPARATE KEY! * Encrypt-Then-MAC * Always MAC after encryption
All Together Now! =================
## Encrypt $key = 'xxxxxxxxxxxx'; $authKey = 'XXXXXXXXXXXX'; $plain = 'This is plain text that I am going to encrypt'; $size = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB ); $iv = mcrypt_create_iv( $size, MCRYPT_DEV_URANDOM ); $ciphertext = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $plain, MCRYPT_MODE_CFB, $iv ); $auth = hash_hmac('sha512', $ciphertext, $authKey); $encrypted = base64_encode($iv . $ciphertext . $auth);
## Decrypt $key = 'xxxxxxxxxxxxxx'; $authKey = 'XXXXXXXXXXXXXX'; $size = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB ); $encrypted = base64_decode($encrypted); $iv = substr($encrypted, 0, $size); $auth = substr($encrypted, -64); $ciphertext = substr($encrypted, $size, -64); if ($auth != hash_hmac('sha512', $ciphertext, $authKey)) { // Auth Failed!!! return false; } $plain = mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CFB, $iv );
Please Don't Do It! =================== * Notice how much code it took * Notice how complex it is * Notice how easy to screw up * Notice how many decisions there are to make!
If you MUST, ============ Use A Library =============
## Common Encryption Needs * Between Client/Server * Use SSL * Really, just use SSL * I'm not kidding, just use SSL * Storage * Use disk encryption * Use database encryption
Really ====== Don't Do It! ============
## Encryption Resources * Zend Framework Encryption * Very good and complete library * Zend Framework 2 * `Zend\Crypt\BlockCipher` * PHP Sec Lib * phpseclib.sourceforge.net * PHP 4+ Compatible * Implements Lots of Algorithms * Pure PHP * Not Many Others * I'm working on CryptLib, but NOT usable * Beware of tutorials online!
Password ======== Storage =======
Passwords ========= Should Be ========= HASHED! ======= Not Encrypted! ==============
## Password Hashes * Use a salt * Defeats Rainbow tables * Makes each hash a "proof of work" * Should be random! * Strong Randomness * Should be SLOW * Salt is not enough * Salted SHA256: 11 BILLION per second * bcrypt: 3200 per second
## Good Algorithms * Slow Algorithms: crypt($password, $salt); pbkdf2($password, $salt, $i); password_hash( $password, PASSWORD_BCRYPT ); $passLib->hash($password); $phpass->hashPassword($pass);
## Cost Parameter * Target: 0.25 Seconds * As slow as you can afford * Depends on hardware * Test it! * Good Defaults: * BCrypt: 10 * PBKDF2: 10000
Simplified ========== Password Hashing ================
## New API for 5.5 * string **password_hash**($pass, $algo, array $options = array()) * Generates salt, hashes password using algo * bool **password_verify**($pass, $hash) * Verifies hash and password, returns boolean * bool **password_needs_rehash**($hash, $algo, $options = array()) * Determines if the hash is the same as specified by algo * array **password_get_info**($hash) * Returns an array of information about the hash
## Example function register($user, $password) { $hash = password_hash($password, PASSWORD_BCRYPT); $this->store($user, $hash); } function login($user, $password) { $hash = $this->fetchHash($user); if (password_verify($password, $hash)) { if (password_needs_rehash($hash, PASSWORD_BCRYPT)) { $hash = password_hash($password, PASSWORD_BCRYPT); $this->store($user, $hash); } $this->startSession(); return true; } return false; }
## Hashing Resources * PHP 5.5 API * wiki.php.net/rfc/password_hash * Password Compat * PHP 5.5 Compatibility * github/ircmaxell/password_compat * PasswordLib * 5.3+, Multiple Algorithms, Portable * github/ircmaxell/PHP-PasswordLib * PHPASS * PHP 4+ * openwall.com/phpass
Seriously ========= Hire an Expert!!! =================
You Have Been ============= Warned ======
1. Questions? 2. Comments? 3. Snide Remarks?
## Anthony Ferrara ## @ircmaxell ## blog.ircmaxell.com ## me@ircmaxell.com