【发布时间】:2011-02-08 11:35:14
【问题描述】:
我需要在 postgresql 上使用 salt 对一些密码进行哈希处理,但我无法找到任何有关如何完成此操作的相关文档。
那么如何在 postgresql 中散列密码(使用一些盐)?
【问题讨论】:
标签: security postgresql hash cryptography salt
我需要在 postgresql 上使用 salt 对一些密码进行哈希处理,但我无法找到任何有关如何完成此操作的相关文档。
那么如何在 postgresql 中散列密码(使用一些盐)?
【问题讨论】:
标签: security postgresql hash cryptography salt
应用程序应使用 bcrypt 或 pbkdf2 等密钥派生函数对其密码进行哈希处理。 Here is more information on secure password storage.
...但有时您仍然需要数据库中的加密函数。
您可以使用pgcrypto 访问 sha256,它是 sha2 家族的成员。请记住 sha0、sha1 md4 和 md5 非常损坏,应该从不用于密码哈希。
以下是哈希密码的好方法:
digest("salt"||"password"||primary_key, "sha256")
盐应该是一个随机生成的大值。这种盐应该受到保护,因为在恢复盐之前无法破坏散列。如果您将盐存储在数据库中,则可以使用 sql 注入将其与密码哈希一起获取。连接主键用于防止两个人拥有相同的密码哈希,即使他们拥有相同的密码。当然这个系统可以改进,但这比我见过的大多数系统要好得多。
通常最好在应用程序访问数据库之前对其进行哈希处理。这是因为查询可以显示在日志中,如果数据库服务器是自己的,那么它们可以启用日志记录以获取明文密码。
【讨论】:
update account set pswhash = crypt('global salt' || 'new password' || 'user created date', gen_salt('sha256')) where account_id = 5 或类似的东西实际上对创建初始哈希有意义?还是我错过了 crypt() 函数的一些内容?
示例和文档:http://www.postgresql.org/docs/8.3/static/pgcrypto.html
UPDATE ... SET pswhash = crypt('new password', gen_salt('md5'));
SELECT pswhash = crypt('entered password', pswhash) FROM ... ;
【讨论】:
update account set pswhash = crypt('global salt' || 'new password' || 'user created date', gen_salt('sha256')) where account_id = 5?还是加盐仍然是一个手动过程?
digest 函数来加密密码,它不够安全。只要确保您使用 Blowfish 算法而不是 MD5。
我问这个问题已经有一段时间了,而且我现在对密码学理论更加熟悉,所以这里是更现代的方法:
sudo apt-get install postgresql // (of course)
sudo apt-get install postgresql-contrib libpq-dev // (gets bcrypt, crypt() and gen_salt())
sudo apt-get install php5-pgsql // (optional if you're using postgresql with php)
// Create your database first, then:
cd `pg_config --sharedir` // Move to the postgres directory that holds these scripts.
echo "create extension pgcrypto" | psql -d yOuRdATaBaSeNaMe // enable the pgcrypo extension
将 :pass 与现有哈希进行比较:
select * from accounts where password_hash = crypt(:pass, password_hash);
//(note how the existing hash is used as its own individualized salt)
使用随机盐创建 :password 的哈希:
insert into accounts (password) values crypt(:password, gen_salt('bf', 8));
//(the 8 is the work factor)
在 php 5.5 及更高版本中有 password_* 函数允许使用 bcrypt 进行简单的密码散列(大约是时候了!),并且对于低于该版本的版本有一个向后兼容库。 通常散列会回退到包装 linux 系统调用以降低 CPU 使用率,尽管您可能希望确保它已安装在您的服务器上。请参阅:https://github.com/ircmaxell/password_compat(需要 php 5.3.7+)
请注意,使用 pg_crypto,密码在从浏览器到 php 再到数据库的传输过程中都是纯文本的。这意味着如果您对数据库日志不小心,它们可以以纯文本形式从查询中记录下来。例如拥有 postgresql 慢查询日志可以从正在进行的登录查询中捕获并记录密码。
如果可以,请使用 php bcrypt,它会减少密码保持未散列的时间。尝试确保您的 linux 系统在它的 crypt() 中安装了 bcrypt,这样它是高性能的。强烈建议至少升级到 php 5.3.7+,因为 php 的实现从 php 5.3.0 到 5.3.6.9 略有错误,并且在 php 5.2.9 及更低版本中不适当地回退到损坏的DES 而没有警告。
如果您想要/需要 in-postgres 散列,安装 bcrypt 是可行的方法,因为默认安装的散列是旧的和损坏的(md5 等)。
以下是有关该主题的更多阅读参考资料:
【讨论】:
password_hash()。 Bcrypt 是当前最先进的密码散列技术,因此它击败了其他选项,无论是在 postgresql 还是 php 中。 Bcrypt 散列在设计上是资源密集型的,因此如果您在 php 中使用它,请尝试从 crypt() 获取 bcrypt 以减少服务器的资源使用。
scram-sha-256 密码方案(来自RFC 7677)。由于它使用了SCRAM,因此在某些情况下它可能是 PHP 的password_* 函数的替代品。