目錄
0×00 前言
0×01 PHP
PHP第一种方案
PHP第二种方案
0×02 JAVA
JAVA第一种方案
JAVA第二种方案
0×03 C# .NET
C#(.NET)第一种方案
C#(.NET)第二种方案
0×04 Ruby
Ruby 第一种方案
Ruby 第二种方案
0×05 Python
Python 第一种方案
Python 第二种方案
0×06 Node.js
Node.js 第一种方案
Node.js 第二种方案
首頁 後端開發 php教程 开发安全指南:如何安全地储存用户密码

开发安全指南:如何安全地储存用户密码

Jun 23, 2016 pm 01:16 PM

0×00 前言

首先如果你对密码学的概念以及使用并不熟悉,或者你正需要进行一些密码学的引导,那么我推荐你阅读一下这篇内容。

此前我们就曾明确的表示,即使是安全建议也应该有个保质期。因此和我们过去发布的大多数博客文章不同,上面那篇内容实际上是处在一种“随时更新”的状态:当对安全的需求变化以及新的攻击形式被发现时,我们都会做出相应的变更。

这里我们提出一个密码安全观点: 不要存储明文密码,而是存储密码的哈希值。

事实上现在,生成安全的密码哈希值非常简单。

但这里有个问题就是,你可能希望别人可以设置一个带密码的帐号,通过这个帐号和密码,别人可以登录到你的程序中,那么这一功能要怎样才能安全的实现?

而解决这个问题也很简单——使用libsodium。它可以为大多数语言提供一个安全的密码哈希API。在1.0.8版本之前它使用的是scrypt算法,但从1.0.9版本开始,它还会提供Argon2,这是从最近的哈希密码对比中精心挑选出来的一个算法。Libsodium会提供对大多数编程语言的绑定。

Libsodium文件

Libsodium源码

注意:这里公布了一个对Argon2i的攻击——Argon2通用密码哈希的变种表示。实际上它的影响并不严重,但它可能会导致一个新的变种(也许是Argon2x,因为它可能会使用XOR而不是覆盖内存来缓解这些攻击)。

如果你因为种种原因无法在安装libsodium和你的要求之间进行调和的话,你还有其他的选择。在准备这篇博客时,我们的团队已经研究了多种编程语言的几个密码哈希库,下面就为大家利用示例代码介绍下。

目前可接受的密码哈希算法主要有:

Argon2 密码哈希比赛的冠军

bcrypt

scrypt

以及密码哈希比赛的其他参赛算法 (Catena, Lyra2, Makwa, and yescrypt)

PBKDF2 最糟糕的一种选择

0×01 PHP

PHP第一种方案

首先确认你使用的版本是否支持PHP。如果支持,那么PHP密码API将能够使用。如果不支持,那么可以尝试进行升级,如果还是不行,检查一下password_compat。

$hash = password_hash($userPassword, PASSWORD_DEFAULT);
登入後複製

显然 password_hash() 使用的是加盐计算的哈希值。根据自己实际情况进行调整,如果硬件支持的话,使用最小绝对值10.12是很好的,其默认的10。

$hash = password_hash($userPassword, PASSWORD_DEFAULT, ['cost' => 12]);
登入後複製

事实上验证一个密码的哈希存储是很简单的:

if (password_verify($userPassword, $hash)) {    // Login successful.    if (password_needs_rehash($userPassword, PASSWORD_DEFAULT, ['cost' => 12])) {        // Recalculate a new password_hash() and overwrite the one we stored previously    }}
登入後複製

在PHP7中,PASSWORD_DEFAULT仍然使用bcrypt。在未来的版本中,它可能会逐渐变为Argon2.

PHP第二种方案

如果你没办法使用libsodium(当然我们强烈建议你使用),你仍然可以用PHP中加密哈希,只需要通过来自PECL 的Dominic Black的Scrypt PHP 扩展即可。

#If you don't have PECL installed, get that first.pecl install scryptecho "extension=scrypt.so" > /etc/php5/mods-available/scrypt.iniphp5enmod scrypt
登入後複製

接下来,把一个PHP包装捆绑在你的工程中。

# Hashing$hash = \Password::hash($userProvidedPassword);# Validationif (\Password::check($userProvidedPassword, $hash)) {    // Logged in successfully.}
登入後複製

0×02 JAVA

JAVA第一种方案

在Java程序中进行安全的密码哈希,除了 libsodium还有jBCrypt,能够提供bcrypt密码哈希算法。

String hash = BCrypt.hashpw(userProvidedPassword, BCrypt.gensalt());
登入後複製

验证一个在Java中的bcrypt hash:

if (BCrypt.checkpw(userProvidedPassword, hash)) {    // Login successful.}
登入後複製

JAVA第二种方案

有一个java实现的scrypt,但它需要你指定参数,而不会提供一个默认值给你。

# Calculating a hashint N = 16384;int r = 8;int p = 1;String hashed = SCryptUtil.scrypt(passwd, N, r, p);# Validating a hashif (SCryptUtil.check(passwd, hashed)) {    // Login successful}
登入後複製

0×03 C# .NET

C#(.NET)第一种方案

我们推荐Martin Steel的BCrypt.NET fork而不是 System.Security.Cryptography.Rfc2898DeriveBytes ,它是 PBKDF2-SHA1 (我们不是说 PBKDF2-SHA1 不安全,但相对来说bcrypt更好一些。

// Calculating a hashstring hash = BCrypt.HashPassword(usersPassword, BCrypt.GenerateSalt());// Validating a hashif (BCrypt.Verify(usersPassword, hash)) {    // Login successful}
登入後複製

C#(.NET)第二种方案

这里同样有一个Scrypt 包 在NuGET中。

// This is necessary:ScryptEncoder encoder = new ScryptEncoder();// Calculating a hashSecureString hashedPassword = encoder.Encode(usersPassword);// Validating a hashif (encoder.Compare(usersPassword, hashedPassword)) {    // Login successful}
登入後複製

0×04 Ruby

Ruby 第一种方案

按照笔者一如既往的规律,这里是一个对 bcrypt密码哈希的 Ruby gem 。

require "bcrypt"# Calculating a hashmy_password = BCrypt::Password.create(usersPassword)# Validating a hashif my_password == usersPassword  # Login successful
登入後複製

要注意的是截止本文发布,该库仍然没有遵循加密编码的最佳实践。因此在他们抽出时间打补丁前都需要考虑到这一点。

Ruby 第二种方案

在Ruby中进行Scrpyt哈希

这也是一个对 bcrypt密码哈希的 Ruby gem 。

require "scrypt"# Calculating a hashpassword = SCrypt::Password.create(usersPassword)# Validating a hashif password == usersPassword  # Login successful
登入後複製

0×05 Python

Python 第一种方案

好了你猜的没错还是使用 bcrypt python 包 ( GitHub )

import bcryptimport hmac# Calculating a hashpassword = b"correct horse battery staple"hashed = bcrypt.hashpw(password, bcrypt.gensalt())# Validating a hash (don't use ==)if (hmac.compare_digest(bcrypt.hashpw(password, hashed), hashed)):    # Login successful
登入後複製

Python开发人员通常更喜欢passlib (Bitbucket),尽管它的API命名并不正确。(”加密” 而不是 “hash”):

from passlib.hash import bcrypt# Calculating a hashhash = bcrypt.encrypt(usersPassword, rounds=12)# Validating a hashif bcrypt.verify(usersPassword, hash):    # Login successful
登入後複製

Python 第二种方案

目前我们发现除了libsodium以外只有 django-scrypt package .可以较为健全的实现。其他的我们还在寻找中。

0×06 Node.js

Node.js 第一种方案

在Node.js上bcrypt( https://www.npmjs.com/package/bcrypt)有两种安全的实现方式,尽管bcrypt看起来是首选。

在下面的例子中,我们大量的使用了Promises来简化错误处理:

var Promise = require("bluebird");var bcrypt = Promise.promisifyAll(require("bcrypt"));function addBcryptType(err) {    // Compensate for `bcrypt` not using identifiable error types    err.type = "bcryptError";    throw err;}// Calculating a hash:Promise.try(function() {    return bcrypt.hashAsync(usersPassword, 10).catch(addBcryptType);}).then(function(hash) {    // Store hash in your password DB.});// Validating a hash:// Load hash from your password DB.Promise.try(function() {    return bcrypt.compareAsync(usersPassword, hash).catch(addBcryptType);}).then(function(valid) {    if (valid) {        // Login successful    } else {        // Login wrong    }});// You would handle errors something like this, but only at the top-most point where it makes sense to do so:Promise.try(function() {    // Generate or compare a hash here}).then(function(result) {    // ... some other stuff ...}).catch({type: "bcryptError"}, function(err) {    // Something went wrong with bcrypt});
登入後複製

Node.js 第二种方案

我们推荐 scrypt for humans,这是一个对开发人员很友好的 node-scrypt 包装器,非常容易使用。

var Promise = require("bluebird");var scrypt = require("scrypt-for-humans");// Calculating a hash:Promise.try(function() {  return scrypt.hash(usersPassword);}).then(function(hash) {  // Store hash for long term use});// Validating a hash:Promise.try(function() {  return scrypt.verifyHash(usersPassword, hash);}).then(function() {  // Login successful}).catch(scrypt.PasswordError, function(err) {  // Login failed});
登入後複製

*原文地址: paragonie ,东二门陈冠希/编译 0xroot后期整理,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1669
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1273
29
C# 教程
1256
24
說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

您如何防止PHP中的SQL注入? (準備的陳述,PDO) 您如何防止PHP中的SQL注入? (準備的陳述,PDO) Apr 15, 2025 am 12:15 AM

在PHP中使用預處理語句和PDO可以有效防範SQL注入攻擊。 1)使用PDO連接數據庫並設置錯誤模式。 2)通過prepare方法創建預處理語句,使用佔位符和execute方法傳遞數據。 3)處理查詢結果並確保代碼的安全性和性能。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

See all articles