PHP mcrypt AES encryption wrapper There are two keys: the main is aes128 and the second is XTEA, used just for randomization of data inside the AES. Randomization is done with secret random key that is not know even if someone knows exactly what is encrypted. Also the key is produced by doing hash many number of times and this hash is salted with the iv so it is not possible to make a dictionary attack with precomputed hashes.

function aes128ctr_en($data,$key,$hash_rounds = 0) {
    //iv is created
    $iv = mcrypt_create_iv(16,MCRYPT_DEV_URANDOM);
    //internal secret random string is created so no one knows what
    //is exactly encoded by main cipher
    $xtea = mcrypt_create_iv(16,MCRYPT_DEV_URANDOM);
    //password is hashed in many rounds to prevent dictionary attack,
    //hashing is done with individual iv for hmac so it make no sense to use
    //precalculated hashes
    for($i=0;$i&lt;=$hash_rounds;++$i) $key = hash_hmac('sha256',$key,$iv,true);
    //string is randomized for use in aes, so no one knows what actually will be encoded
    //this is not actual encoding so password is stored inside with xtea encoded string,
    //second half of this password is used as IV for xtea
    //again: THIS IS NOT ACTUAL ENCODING
    $data = $xtea.mcrypt_encrypt('xtea',$xtea,$data,'ofb',substr($xtea,8));
    //hash is added to check if return string is really what we looked for,
    //must match with string on decoding
    $data = hash('md5',$data,true).$data;
    //actual encoding, IV is prepended to encrypted string
    return $iv.mcrypt_encrypt('rijndael-128',$key,$data,'ctr',$iv);
}

function aes128ctr_de($data,$key,$hash_rounds = 0) {
    $iv = substr($data,0,16);
    $data = substr($data,16);
    for($i=0;$i&lt;=$hash_rounds;++$i) $key = hash_hmac('sha256',$key,$iv,true);
    $data = mcrypt_decrypt('rijndael-128',$key,$data,'ctr',$iv);
    $md5 = substr($data,0,16);
    $data = substr($data,16);
    if (hash('md5',$data,true)!==$md5) return false;
    $xtea = substr($data,0,16);
    $data = substr($data,16);
    return mcrypt_decrypt('xtea',$xtea,$data,'ofb',substr($xtea,8));
}

$key = 'suPer_secret aAnd L10ng ppswrd$%';
$encrypted = aes128ctr_en('the bomb will blow up at 1 pm',$key,12345);
echo aes128ctr_de($encrypted,$key,12345);


I really don't have knowledge to make it better. I'm not that educated in all this to read RFCs and make algorithms out of it. I'm also constrained to methods that are precompiled in core PHP binary as I want these methods to be able to run on remote servers.
You should use a key strengthening function like PKBDF2, scrypt or bcrypt to generate a key from the password.
The part with XTEA is useless: you're relying on security through obscurity.
You shouldn't hash before encrypting if you want to ensure the data has not been tampered with. Use HMAC SHA-256 on the encrypted data.

And finally: don't write your own crypto algorithm. Use well known and audited solutions.