/** * Encrypt data returning a JSON encoded array safe for storage in a database * or file. The array has the following structure before it is encoded: * array( * 'cdata' => 'Encrypted data, Base 64 encoded', * 'iv' => 'Base64 encoded IV', * 'algo' => 'Algorythm used', * 'mode' => 'Mode used', * 'mac' => 'Message Authentication Code' * ) * * @param mixed $data * Data to encrypt. * * @param string $key * Key to encrypt data with. * * @return string * Serialized array containing the encrypted data along with some meta data. */ public function encrypt($data, $key) { /* Make sure both algorithm and mode are either block or non-block. */ $isBlockCipher = mcrypt_module_is_block_algorithm($this->_algo); $isBlockMode = mcrypt_module_is_block_algorithm_mode($this->_mode); if ($isBlockCipher !== $isBlockMode) { throw new \phpSec\Exception\InvalidAlgorithmParameterException('You can not mix block and non-block ciphers and modes'); return false; } $td = mcrypt_module_open($this->_algo, '', $this->_mode, ''); /* Check key size. */ $keySize = strlen($key); $keySizes = mcrypt_enc_get_supported_key_sizes($td); if (count($keySizes) > 0) { /* Encryption method requires a specific key size. */ if (!in_array($keySize, $keySizes)) { throw new \phpSec\Exception\InvalidKeySpecException('Key is out of range. Should be one of: ' . implode(', ', $keySizes)); return false; } } else { /* 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, $key1, $iv); /* Prepeare the array with data. */ $serializedData = serialize($data); /* Enable padding of data if block cipher moode. */ if (mcrypt_module_is_block_algorithm_mode($this->_mode) === true) { $this->_padding = true; } /* Add padding if enabled. */ if ($this->_padding === true) { $block = mcrypt_enc_get_block_size($td); $serializedData = $this->pad($block, $serializedData); $encrypted['padding'] = 'PKCS7'; } $encrypted['algo'] = $this->_algo; /* Algorithm used to encrypt. */ $encrypted['mode'] = $this->_mode; /* Algorithm mode. */ $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($this->pbkdf2($encrypted['cdata'], $key2, 1, 32)); return json_encode($encrypted); }
mcrypt_generic_init($td, $key, $iv); $encrypted = mcrypt_generic($td, "This is very important data"); VERIFY($encrypted !== "This is very important data"); mcrypt_generic_deinit($td); mcrypt_generic_init($td, $key, $iv); $decrypted = mdecrypt_generic($td, $encrypted); mcrypt_generic_end($td); mcrypt_module_close($td); VS($decrypted, "This is very important data"); VERIFY(in_array("blowfish", mcrypt_list_algorithms())); VERIFY(in_array("cbc", mcrypt_list_modes())); VS(mcrypt_module_get_algo_block_size("blowfish"), 8); VS(mcrypt_module_get_algo_key_size("blowfish"), 56); VS(mcrypt_module_get_supported_key_sizes("blowfish"), array()); VS(mcrypt_module_get_supported_key_sizes("twofish"), array(16, 24, 32)); VS(mcrypt_module_is_block_algorithm_mode("cbc"), true); VS(mcrypt_module_is_block_algorithm("blowfish"), true); VS(mcrypt_module_is_block_mode("cbc"), true); VS(mcrypt_module_self_test(MCRYPT_RIJNDAEL_128), true); VS(mcrypt_module_self_test("bogus"), false); $text = "boggles the inivisble monkey will rule the world"; $key = "very secret key"; $iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $enc = mcrypt_encrypt(MCRYPT_XTEA, $key, $text, MCRYPT_MODE_ECB, $iv); VS(bin2hex($enc), "f522c62002fa16129c8576bcddc6dd0f7ea81991103ba42962d94c8bfff3ee660d53b187d7e989540abf5a729c2f7baf"); $crypttext = mcrypt_decrypt(MCRYPT_XTEA, $key, $enc, MCRYPT_MODE_ECB, $iv); VS($crypttext, $text); ////////////////////////////////////////////////////////////////////// $key = "123456789012345678901234567890123456789012345678901234567890"; $CC = "4007000000027";
/** * Checks whether the given arguments are good to be used for encryption/decryption. * * @param string $cipher * @param binary $key * @param string $operationMode * @param bool $strict Whether to true exceptions upon failure. Defaults to false. * @throws Exception * @return bool */ public static function isCipherable($cipher, $key, $operationMode, $strict = false) { // Check whether the cipher is supported. $supportedCiphers = self::getSupportedCiphers(); if (in_array($cipher, $supportedCiphers) === false) { if ($strict === true) { throw new Exception("The cipher '{$cipher}' is not supported on this system. The following is a list of supported ciphers: " . implode(', ', $supportedCiphers)); } return false; } // Check whether the block mode is supported. $supportedModes = self::getSupportedModes(); if (in_array($operationMode, $supportedModes) === false) { if ($strict === true) { throw new Exception("The block mode '{$operationMode}' is not supported on this system. The following is a list of supported operation modes: " . implode(', ', $supportedModes)); } return false; } // We discourage ECB. if ($operationMode === 'ecb') { trigger_error("You should not use 'ecb' as your block mode due to its low strength.", E_USER_WARNING); } // Make sure the key size is okay. $supportedKeySizes = mcrypt_module_get_supported_key_sizes($cipher); $keySize = strlen((string) $key); if (in_array($keySize, $supportedKeySizes) === false) { if ($strict === true) { throw new Exception("The cipher '{$cipher}' does not support a key size of '{$keySize}'. The following is a list of supported key sizes for '{$cipher}': " . implode(', ', $supportedKeySizes)); } return false; } // Make sure the person is not mixing non-block cipher modes with block ciphers and vice versa. if (mcrypt_module_is_block_algorithm($cipher) === true) { // He must be using also a block algorithm mode. if (mcrypt_module_is_block_algorithm_mode($operationMode) === false) { if ($strict === true) { throw new Exception("You cannot encrypt with a block algorithm like '{$cipher}' using a non-block algorithm mode '{$operationMode}'."); } return false; } } else { // He must be using a non-block algorithm mode. if (mcrypt_module_is_block_algorithm_mode($operationMode) === true) { if ($strict === true) { throw new Exception("You cannot encrypt with a non-block algorithm like '{$cipher}' using a block algorithm mode '{$operationMode}'."); } return false; } } }
<?php var_dump(mcrypt_module_is_block_algorithm_mode(MCRYPT_MODE_CBC)); var_dump(mcrypt_module_is_block_algorithm_mode(MCRYPT_MODE_ECB)); var_dump(mcrypt_module_is_block_algorithm_mode(MCRYPT_MODE_STREAM)); var_dump(mcrypt_module_is_block_algorithm_mode(MCRYPT_MODE_OFB));