diff --git a/lib/phpSec/Crypt/Crypto.php b/lib/phpSec/Crypt/Crypto.php index bdcba45..573de07 100644 --- a/lib/phpSec/Crypt/Crypto.php +++ b/lib/phpSec/Crypt/Crypto.php @@ -77,19 +77,24 @@ public function encrypt($data, $key) { return false; } } else { - /* No spsecific size is needed. */ + /* No specific size is needed. */ if($keySize == 0 || $keySize > mcrypt_enc_get_key_size($td)) { throw new \phpSec\Exception\InvalidKeySpecException('Key is out of range. Should be between 1 and ' . mcrypt_enc_get_key_size($td).' bytes.'); return false; } } + /* Using PBKDF with constant salts dedicated to each purpose + * can securely derivce two keys from one */ + $key1 = $this->pbkdf2($key, "encrypt", 1, $keySize); + $key2 = $this->pbkdf2($key, "HMAC", 1, $keySize); + /* Create IV. */ $rnd = $this->psl['crypt/rand']; $iv = $rnd->bytes(mcrypt_enc_get_iv_size($td)); /* Init mcrypt. */ - mcrypt_generic_init($td, $key, $iv); + mcrypt_generic_init($td, $key1, $iv); /* Prepeare the array with data. */ $serializedData = serialize($data); @@ -111,7 +116,7 @@ public function encrypt($data, $key) { $encrypted['iv'] = base64_encode($iv); /* Initialization vector, just a bunch of randomness. */ $encrypted['cdata'] = base64_encode(mcrypt_generic($td, $serializedData)); /* The encrypted data. */ $encrypted['mac'] = base64_encode( /* The message authentication code. Used to make sure the */ - $this->pbkdf2($encrypted['cdata'], $key, 1000, 32) /* message is valid when decrypted. */ + $this->pbkdf2($encrypted['cdata'], $key2, 1, 32) /* message is valid when decrypted. */ ); return json_encode($encrypted); } @@ -148,14 +153,20 @@ public function decrypt($data, $key) { $td = mcrypt_module_open($data['algo'], '', $data['mode'], ''); $block = mcrypt_enc_get_block_size($td); + /* Using PBKDF with constant salts dedicated to each purpose + * can securely derivce two keys from one */ + $keySize = strlen($key); + $key1 = $this->pbkdf2($key, "encrypt", 1, $keySize); + $key2 = $this->pbkdf2($key, "HMAC", 1, $keySize); + /* Check MAC. */ - if(base64_decode($data['mac']) != $this->pbkdf2($data['cdata'], $key, 1000, 32)) { + if(base64_decode($data['mac']) != $this->pbkdf2($data['cdata'], $key2, 1, 32)) { throw new \phpSec\Exception\GeneralSecurityException('Message authentication code invalid'); return false; } /* Init mcrypt. */ - mcrypt_generic_init($td, $key, base64_decode($data['iv'])); + mcrypt_generic_init($td, $key1, base64_decode($data['iv'])); $decrypted = rtrim(mdecrypt_generic($td, base64_decode($this->stripPadding($block, $data['cdata'])))); diff --git a/tests/phpSec/Crypt/CryptoTest.php b/tests/phpSec/Crypt/CryptoTest.php index 298ebb4..ae11faf 100644 --- a/tests/phpSec/Crypt/CryptoTest.php +++ b/tests/phpSec/Crypt/CryptoTest.php @@ -7,12 +7,19 @@ public function testCrypto() { $str = 'foobaz'; $key = '123abc12123abc12'; + $badkey = '123abcR77123abc12'; + $encrypted = $crypto->encrypt($str, $key); $decrypted = $crypto->decrypt($encrypted, $key); $this->assertEquals($decrypted, $str); + try { + $ret = $crypto->decrypt($encrypted, $badkey); + }catch(Exception $e){ + $this->assertEquals("Message authentication code invalid",$e->getMessage()); + } } -} \ No newline at end of file +}