59

我需要在 postgresql 上用盐对一些密码进行哈希处理,但我找不到任何有关如何完成此操作的相关文档。

那么如何在 postgresql 中散列密码(带有一些盐)?

4

3 回答 3

95

自从我问这个问题以来已经有一段时间了,而且我现在对密码学理论更加熟悉,所以这里是更现代的方法:

推理

  • 不要使用 md5。不要使用单个循环的 sha-family 快速哈希。快速哈希可以帮助攻击者,所以你不希望这样。
  • 请改用资源密集型哈希,例如 bcrypt。Bcrypt 是经过时间考验的,并且可以扩展为面向未来的能力。
  • 不要费心滚动你自己的盐,你可能会搞砸自己的安全性或可移植性,依靠 gen_salt() 来生成它自己的令人敬畏的独特的每个使用的盐。
  • 一般来说,不要做白痴,不要尝试编写自己的本土加密货币,只需使用聪明人提供的东西。

Debian/Ubuntu 安装包

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)

在数据库中的 postgresql 中激活 crypt() 和 bcrypt

// 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

在查询中使用 crypt() 和 gen_salt()

将 :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)

From-in-Php bcrypt 散列稍微可取

php 5.5 及更高版本中有一些password_*函数允许使用 bcrypt 进行简单的密码散列(大约是时候了!),并且对于低于该版本的版本有一个向后兼容库。 通常,散列会退回到包装 linux 系统调用以降低 CPU 使用率,尽管您可能希望确保它已安装在您的服务器上。请参阅:https ://github.com/ircmaxell/password_compat (需要 php 5.3.7+)

小心记录

请注意,使用 pg_crypto,密码在从浏览器到 php 到数据库的传输过程中都是纯文本的。这意味着如果您对数据库日志不小心,它们可以从查询中以纯文本形式记录。例如,拥有一个 postgresql 慢查询日志可以从正在进行的登录查询中捕获并记录密码。

总之

如果可以,请使用 php bcrypt,它会减少密码保持未散列的时间。尝试确保您的 linux 系统中安装了 bcrypt 以确保其crypt()性能。强烈建议至少升级到 php 5.3.7+,因为 php 的实现从 php 5.3.0 到 5.3.6.9 略有错误,并且DES在 php 5.2.9 及更低版本中不适当地回退到损坏而没有警告。

如果您想要/需要 in-postgres 散列,安装 bcrypt 是可行的方法,因为默认安装的散列是旧的和损坏的(md5 等)。

以下是有关该主题的更多阅读参考资料:

于 2013-09-08T18:58:12.593 回答
16

应用程序应使用 bcrypt 或 pbkdf2 等密钥派生函数对其密码进行哈希处理。 这是有关安全密码存储的更多信息

...但有时您仍然需要数据库中的密码功能。

您可以使用pgcrypto访问 sha256,它是 sha2 系列的成员。请记住 sha0、sha1 md4 和 md5 非常损坏,不应该用于密码哈希。

以下是哈希密码的好方法:

digest("salt"||"password"||primary_key, "sha256")

盐应该是一个很大的随机生成的值。这种盐应该受到保护,因为在恢复盐之前无法破坏散列。如果您将盐存储在数据库中,则可以使用 sql 注入将其与密码哈希一起获取。连接主键用于防止两个人拥有相同的密码哈希,即使他们拥有相同的密码。当然这个系统可以改进,但这比我见过的大多数系统要好得多。

通常,最好在应用程序访问数据库之前对其进行哈希处理。这是因为查询可以显示在日志中,如果数据库服务器是自己的,那么他们可以启用日志记录以获取明文密码。

于 2010-04-15T16:33:16.637 回答
10

示例和文档: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 ... ;
于 2010-04-15T16:35:59.490 回答