【发布时间】:2014-08-14 16:01:00
【问题描述】:
目前我有一个 PHP 脚本,它通过 IMAP 连接到邮件服务器并将新电子邮件解析到 MySQL。连接到邮件服务器的凭据使用纯文本存储在 MySQL 中,有没有办法可以加密存储在 MySQL 中的密码?
【问题讨论】:
-
由于您连接到外部资源,您需要加密密码而不是散列密码。散列密码使您无法取回纯文本密码。
目前我有一个 PHP 脚本,它通过 IMAP 连接到邮件服务器并将新电子邮件解析到 MySQL。连接到邮件服务器的凭据使用纯文本存储在 MySQL 中,有没有办法可以加密存储在 MySQL 中的密码?
【问题讨论】:
MySQL 支持AES_ENCRYPT() 函数。您可以在将其 INSERT 到数据库时进行加密,并在 SELECT 退出时对其进行解密。
阅读我链接到的文档以获取示例。
然后,当您使用明文密码进行 imap_open() 时,请确保使用端口 993 与 IMAP 服务器建立 TLS 加密连接。
【讨论】:
取决于电子邮件服务器需要验证的内容。如果密码需要使用纯文本发送(可能是因为电子邮件服务器本身对其进行哈希处理),您应该加密您的密码,然后将其解密,然后再将其发送到电子邮件服务器。
如果您可以向服务器发送散列密码,请使用散列函数(md5、sha1、sha512、...)对其进行散列。
hash('sha1', $password);
sha1($password); // Same result as above.
如果你必须加密(为了能够解密),你可以使用 mcrypt 或 openssl。
http://php.net/manual/en/function.mcrypt-encrypt.php http://php.net//manual/en/function.openssl-encrypt.php
这里的区别在于哈希密码不能被取消哈希。可以解密加密的密码。
【讨论】:
password_hash php.net/manual/en/function.password-hash.php
哈希密码的目的是在数据库被黑客入侵的情况下确保最终用户的隐私和机密性。显然你不能使用哈希函数,因为你的脚本需要读回 imap 密码,所以你应该使用一些对称加密函数(例如 AES、blowfish、3DES 等)对其进行加密。现在您面临存储对称密钥材料的位置的问题:将其存储在同一个数据库中完全是愚蠢的,因为破解数据库意味着读取密钥。您可以在脚本或外部 txt 文件中硬编码密钥材料:现在黑客应该破坏 mysql 服务器和 web 域以检索 imap 密码,这是您可以使用标准 php+ 达到的最高安全级别mysql 通用域。
【讨论】:
我使用这些功能或它们的一些变体进行登录。它往往非常安全,因为它会对密码进行加盐并对其进行哈希处理。
<?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;
}
}
?>
【讨论】: