Currently I have a PHP script that connect to a mail server via IMAP and parse new emails to MySQL. credentials to connect to the mail server are stored in MySQL using plain
MySQL supports a AES_ENCRYPT() function. You can encrypt as you INSERT it to the database, and decrypt it as you SELECT it back out.
Read the documentation I linked to for examples.
Then make sure you use port 993 for a TLS encrypted connection to the IMAP server when you imap_open() with the plaintext password.
Depending on what the email server needs to authenticate. If the passwords need to be sent using plain text (maybe because the email server hashes it itself), you should encrypt your password and then decrypt it before send it to the email server.
If you can send a hashed password to the server, hash it using a hash function (md5, sha1, sha512, ...).
hash('sha1', $password);
sha1($password); // Same result as above.
If you have to encrypt (in order to be able to decrypt), you can use mcrypt or openssl.
http://php.net/manual/en/function.mcrypt-encrypt.php http://php.net//manual/en/function.openssl-encrypt.php
The difference here is that a hashed password can't be unhashed. An encrypted password can be decrypted.
I use these functions or some variation of them for login. It tends to be pretty secure, as it salts the passwords and hashes them.
<?php
function password_encrypt($password) {
// Tells PHP to use Blowfish with a "cost" of 10
$hash_format = "$2y$10$";
// Blowfish salts should be 22-characters or more
$salt_length = 22;
$salt = generate_salt($salt_length);
$format_and_salt = $hash_format . $salt;
$hash = crypt($password, $format_and_salt);
return $hash;
}
function generate_salt($length) {
// Not 100% unique, not 100% random, but good enough for a salt
// MD5 returns 32 characters
$unique_random_string = md5(uniqid(mt_rand(), true));
// Valid characters for a salt are [a-zA-Z0-9./]
$base64_string = base64_encode($unique_random_string);
// But not '+' which is valid in base64 encoding
$modified_base64_string = str_replace('+', '.', $base64_string);
// Truncate string to the correct length
$salt = substr($modified_base64_string, 0, $length);
return $salt;
}
function password_check($password, $existing_hash) {
// existing hash contains format and salt at start
$hash = crypt($password, $existing_hash);
if ($hash === $existing_hash) {
return true;
} else {
return false;
}
}
function attempt_login($username, $password) {
$admin = find_admin_by_username($username);
if ($admin) {
// found admin, now check password
if (password_check($password, $admin["hashed_password"])) {
// password matches
return $admin;
} else {
// password does not match
return false;
}
} else {
// admin not found
return false;
}
}
?>
The point of hashing passwords is to ensure privacy&confidentiality for the end user in the case the database get hacked. Obviously you can't use hash functions because your script needs to read back the imap password so you should encrypt it with some symmetric crypt function (e.g. AES, blowfish, 3DES and such). Now you're facing the problem of where to store the symmetric key material: storing it in the same database is completely dumb 'cos hacking the database would mean reading the key. You could hard-code the key material inside the script or in an external txt file: now the hacker should compromise both the mysql server AND the web domain to retrieve the imap password and that's the maximum security level you can reach with a standard php+mysql general purpose domain.