在 Django 專案中,密碼管理是確保系統安全的重要環節。本文將介紹如何運用 Django 內建功能實作密碼變更與重置,並深入探討如何強化密碼安全策略,例如使用密碼雜湊演算法 PBKDF2、鹽值雜湊和金鑰匯出函式等技術。同時,我們也將示範如何自訂密碼驗證器,以滿足專案的特定安全需求。透過這些方法,可以有效提升 Django 應用程式的安全性,保護使用者帳號資訊。

密碼變更和驗證

密碼變更和驗證是密碼管理的兩個重要方面。使用者需要能夠變更自己的密碼,而系統需要驗證新密碼是否符合安全要求。為了實作這個功能,我們可以使用 Django 的內建密碼變更檢視和表單。

from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.views import PasswordChangeView

class CustomPasswordChangeForm(PasswordChangeForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['old_password'].widget.attrs['class'] = 'form-control'
        self.fields['new_password1'].widget.attrs['class'] = 'form-control'
        self.fields['new_password2'].widget.attrs['class'] = 'form-control'

class CustomPasswordChangeView(PasswordChangeView):
    form_class = CustomPasswordChangeForm
    template_name = 'password_change.html'
    success_url = '/accounts/profile/'

    def form_valid(self, form):
        form.save()
        update_session_auth_hash(self.request, form.user)
        return super().form_valid(form)

密碼重置

密碼重置是另一個重要的功能,允許使用者在忘記密碼的情況下重置密碼。為了實作這個功能,我們可以使用 Django 的內建密碼重置檢視和表單。

from django.contrib.auth import views as auth_views
from django.urls import path

urlpatterns = [
    path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

密碼安全

密碼安全是密碼管理的另一個重要方面。為了保護使用者密碼,我們可以使用鹽值雜湊和金鑰匯出函式來抵禦密碼破解和暴力攻擊。

import hashlib
import os

def hash_password(password):
    salt = os.urandom(16)
    hashed_password = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
    return salt + hashed_password

def verify_password(stored_password, provided_password):
    salt = stored_password[:16]
    stored_hash = stored_password[16:]
    provided_hash = hashlib.pbkdf2_hmac('sha256', provided_password.encode('utf-8'), salt, 100000)
    return provided_hash == stored_hash

密碼變更工作流程

在前一章中,您將 URL 路徑對映到一組內建的 Django 檢視。您使用了這些檢視中的兩個,LoginView 和 LogoutView,來建立一個身份驗證工作流程。在本節中,我將向您展示另一個由兩個檢視組成的工作流程:PasswordChangeView 和 PasswordChangeDoneView。

您的專案已經使用了這些檢視的內建工作流程,您在前一章中已經完成了這項工作。啟動您的伺服器,如果它尚未執行,重新以 Bob 的身份登入,並將您的瀏覽器指向您對映到 PasswordChangeView 的 URL。這個檢視會渲染一個簡單的表單,允許使用者變更密碼。這個表單包含三個必填欄位:使用者的密碼、新的密碼和新的密碼確認。

注意新密碼欄位旁邊的四個輸入約束。這些約束代表專案的密碼策略,這是一套規則,旨在防止使用者選擇弱密碼。PasswordChangeView 在表單提交時強制執行這個策略。

Django 專案的密碼策略由一系列密碼驗證器定義,用於確保密碼強度。每個密碼驗證器強制執行單個約束。這個設定預設為空列表,但每個生成的 Django 專案都組態了四個內建的驗證器。

預設密碼策略

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

UserAttributeSimilarityValidator 拒絕任何與使用者名稱稱、第一名稱、姓氏或電子郵件相似的密碼。這防止了 Mallory 取得使用者的密碼。

MinimumLengthValidator 拒絕任何太短的密碼。這防止了 Mallory 使用暴力破解的方式闖入由玄貓保護的帳戶。這個驗證器預設拒絕任何少於八個字元的密碼。

CommonPasswordValidator 拒絕在 20,000 個常用密碼列表中找到的任何密碼。

密碼驗證器組態

您可以組態密碼驗證器來修改其行為。例如,您可以修改 UserAttributeSimilarityValidator 來嚴格測試三個自定義屬性。

{
    'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    'OPTIONS': {
        'user_attributes': ('custom', 'attribute', 'names'),
        'max_similarity': 0.6,
    }
}

您也可以修改 MinimumLengthValidator 來強制執行更長的密碼。

{
    'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    'OPTIONS': {
        'min_length': 12,
    }
}

圖表翻譯

以下是密碼驗證器的 Mermaid 圖表:

  flowchart TD
    A[使用者輸入密碼] --> B[UserAttributeSimilarityValidator]
    B --> C[MinimumLengthValidator]
    C --> D[CommonPasswordValidator]
    D --> E[密碼驗證結果]

這個圖表顯示了密碼驗證的流程,從使用者輸入密碼到密碼驗證結果。每個驗證器都會檢查密碼是否符合特定的約束,如果不符合,就會拒絕密碼。

自訂密碼驗證器

在 Django 中,密碼驗證器是一種用於檢查密碼強度和安全性的工具。預設情況下,Django 提供了幾種內建的密碼驗證器,例如 NumericPasswordValidator,它可以拒絕純數字密碼。但是,為了進一步加強密碼政策,我們可以建立自訂的密碼驗證器。

建立自訂密碼驗證器

首先,建立一個名為 validators.py 的檔案,位於您的專案的 profile_info 目錄中。在這個檔案中,新增以下程式碼:

from django.utils.translation import gettext_lazy as _

class PassphraseValidator:
    def __init__(self, dictionary_file='/usr/share/dict/words'):
        self.min_words = 4
        with open(dictionary_file) as f:
            self.words = set(word.strip() for word in f)

    def get_help_text(self):
        return _('您的密碼必須包含 %s 個詞彙' % self.min_words)

    def validate(self, password, user=None):
        tokens = password.split(' ')
        if len(tokens) < self.min_words:
            too_short = _('密碼需要 %s 個詞彙' % self.min_words)
            raise ValidationError(too_short, code='too_short')
        if not all(token in self.words for token in tokens):
            not_passphrase = _('密碼不是一個詞彙短語')
            raise ValidationError(not_passphrase, code='not_passphrase')

這個 PassphraseValidator 類別負責驗證密碼是否是一個四個詞彙的短語。它使用一個字典檔案來檢查每個詞彙是否有效。

組態自訂密碼驗證器

要使用這個自訂密碼驗證器,需要在 Django 的設定檔案中進行組態。新增以下程式碼到您的 settings.py 檔案中:

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'profile_info.validators.PassphraseValidator',
    },
]

這樣,Django 就會使用我們自訂的 PassphraseValidator 來驗證密碼。

使用自訂密碼驗證器

現在,當使用者嘗試設定一個新密碼時,Django 會使用我們的自訂密碼驗證器來檢查密碼是否符合要求。如果密碼不符合要求,Django 會顯示一個錯誤訊息,告訴使用者密碼需要包含四個詞彙。

這樣,透過建立自訂密碼驗證器,我們可以進一步加強密碼政策,確保使用者的密碼更加安全。

密碼驗證和儲存機制

在 Django 中,密碼驗證是一個重要的安全機制。預設情況下,Django 使用四種原生密碼驗證器來檢查密碼的強度。然而,我們可以自訂密碼驗證器以滿足特定的需求。

自訂密碼驗證器

我們可以建立一個自訂密碼驗證器,稱為 PassphraseValidator,來驗證密碼是否符合特定的規則。這個驗證器可以檢查密碼是否包含至少 4 個單詞。

# profile_info/validators.py
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _

class PassphraseValidator:
    def __init__(self, dictionary_file=None):
        self.dictionary_file = dictionary_file

    def validate(self, password, user=None):
        # 驗證密碼是否包含至少 4 個單詞
        words = password.split()
        if len(words) < 4:
            raise ValidationError(_('密碼必須包含至少 4 個單詞'))

    def get_help_text(self):
        return _('密碼必須包含至少 4 個單詞')

啟用自訂密碼驗證器

要啟用自訂密碼驗證器,我們需要在 settings.py 中設定 AUTH_PASSWORD_VALIDATORS

# settings.py
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'profile_info.validators.PassphraseValidator',
        'OPTIONS': {
            'dictionary_file': '/path/to/dictionary.txt.gz',
        }
    },
]

密碼儲存機制

密碼儲存機制是指如何將密碼儲存在資料函式庫中。有三種常見的密碼儲存方法:明文儲存、密鑰儲存和雜湊值儲存。

  • 明文儲存:這是最不安全的方法,密碼被儲存為明文。
  • 密鑰儲存:這種方法使用加密演算法將密碼加密儲存。
  • 雜湊值儲存:這種方法使用雜湊演算法將密碼轉換為雜湊值儲存。

雜湊值儲存是最安全的方法,因為即使攻擊者獲得了雜湊值,也無法逆向推匯出原始密碼。

  flowchart TD
    A[密碼] --> B[雜湊演算法]
    B --> C[雜湊值]
    C --> D[資料函式庫儲存]

圖表翻譯:

上述流程圖描述了密碼儲存的過程。首先,密碼被輸入到系統中。然後,密碼被傳遞到雜湊演算法中,雜湊演算法將密碼轉換為雜湊值。最後,雜湊值被儲存到資料函式庫中。

在下一節中,我們將討論如何安全地儲存密碼。

密碼儲存的誤區和正確方法

在資訊安全領域中,密碼儲存是一個至關重要的議題。許多組織為了吸引注意力,經常使用聳人聽聞的標題來描述密碼儲存的安全性問題。例如,2019年初,Facebook被發現將密碼儲存為明文,引起了廣泛的關注。然而,事實上,Facebook並不是故意將密碼儲存為明文,而是意外地將其記錄下來。

這種情況固然令人遺憾,但與聳人聽聞的標題所描述的內容大不相同。如果您在網際網路上搜尋「儲存密碼為明文」,您可以找到類似的聳人聽聞的標題,描述了雅虎和谷歌等公司的安全性事件。儲存密碼為密鑰並不比儲存密碼為明文好多少。在這種情況下,系統會將每個密碼加密並儲存密鑰。當使用者登入時,系統會加密輸入的密碼並將其與儲存的密鑰進行比較。

密碼儲存的錯誤方法

儲存加密密碼是一個危險的做法,因為如果攻擊者獲得了密碼儲存函式庫和加密金鑰的未經授權存取權,他就可以存取每個使用者的帳戶。系統管理員通常具有這兩種存取許可權,因此儲存加密密碼是一個容易被惡意系統管理員或能夠操縱系統管理員的攻擊者所利用的目標。

2013年,Adobe公司的超過3,800萬使用者的加密密碼被洩露和公開。這些密碼使用3DES加密演算法的ECB模式進行加密。這些密碼在一個月內就被逆向工程或破解了。

正確的密碼儲存方法

任何現代的身份驗證系統都不會儲存您的密碼;它會對您的密碼進行雜湊。當您登入時,系統會比較輸入的密碼的雜湊值與儲存的雜湊值。如果兩個值匹配,您就會被驗證。如果兩個值不匹配,您需要再試一次。

密碼管理是加密雜湊函式屬性的一個很好的現實世界範例。與加密演算法不同,雜湊函式是單向的;密碼很容易被驗證,但很難被還原。碰撞阻力(collision resistance)的重要性是顯而易見的;如果兩個密碼碰撞,具有匹配的雜湊值,則可以使用任意一個密碼來存取相同的帳戶。

密碼破解的例子

2012年,超過600萬個LinkedIn密碼的雜湊值被洩露和發布到一個俄羅斯的駭客論壇。當時,LinkedIn使用SHA1雜湊函式來雜湊密碼。兩週內,超過90%的密碼被破解。

這些密碼如何被如此快速地破解?假設現在是2012年,Mallory想要破解最近發布的雜湊值。她下載了包含洩露的使用者名稱和SHA1雜湊值的資料集。

內容解密:

本文主要討論了密碼儲存的安全性問題,包括儲存密碼為明文和儲存密碼為密鑰的錯誤方法。同時,也介紹了使用雜湊函式來對密碼進行雜湊的正確方法。文章還提到了LinkedIn密碼破解的例子,強調了碰撞阻力的重要性和使用安全的雜湊函式的必要性。

  flowchart TD
    A[密碼輸入] --> B[雜湊函式]
    B --> C[儲存雜湊值]
    C --> D[登入驗證]
    D --> E[比較雜湊值]
    E --> F[驗證成功或失敗]

圖表翻譯:

此圖表示了密碼儲存和驗證的流程。首先,使用者輸入密碼,然後密碼被雜湊函式處理,生成雜湊值。接下來,雜湊值被儲存到資料函式庫中。當使用者登入時,系統會比較輸入的密碼的雜湊值與儲存的雜湊值。如果兩個值匹配,驗證成功;否則,驗證失敗。這個流程確保了密碼的安全性和保密性。

密碼安全:抵禦彩虹表攻擊

在前面的章節中,我們討論了密碼安全的重要性和常見的攻擊方法。其中,彩虹表攻擊是一種常見的方法,攻擊者可以使用預先計算的雜湊值表來快速地破解密碼。為了抵禦這種攻擊,salted hashing是一種有效的方法。

什麼是salted hashing?

salted hashing是一種計算雜湊值的方法,透過在原始訊息中新增一個隨機的salt值,然後計算雜湊值。這樣,即使兩個訊息相同,也會產生不同的雜湊值。salt值通常是一個隨機的位元組串,與訊息一起作為輸入傳入雜湊函式。

salted hashing的優點

salted hashing有以下優點:

  • 個人化雜湊值:salted hashing可以為每個訊息產生一個唯一的雜湊值,即使兩個訊息相同,也會產生不同的雜湊值。
  • 抵禦彩虹表攻擊:由於salt值是隨機的,攻擊者無法預測salt值,因此無法使用彩虹表攻擊。
  • 安全性提高:salted hashing可以提高密碼的安全性,因為攻擊者需要花費更多的時間和資源來破解密碼。

實作salted hashing

以下是使用BLAKE2實作salted hashing的例子:

from hashlib import blake2b
import secrets

# 產生一個隨機的salt值
salt = secrets.token_bytes(16)

# 訊息
message = b"password"

# 計算雜湊值
hash_value = blake2b(message, salt=salt)

print(hash_value.hexdigest())

在這個例子中,我們使用BLAKE2演算法計算雜湊值,並使用secrets模組產生一個隨機的salt值。然後,我們將訊息和salt值一起傳入BLAKE2演算法,計算雜湊值。

圖表翻譯:
  flowchart TD
    A[訊息] --> B[新增salt值]
    B --> C[計算雜湊值]
    C --> D[產生唯一雜湊值]
    D --> E[提高密碼安全性]

這個圖表展示了salted hashing的過程,從新增salt值到計算雜湊值,最終產生一個唯一的雜湊值,提高密碼的安全性。

密碼雜湊與金鑰衍生函式

在密碼安全的世界中,快速的雜湊函式往往不是最佳選擇。事實上,密碼雜湊是一個特殊的情況,效率低下反而是有益的。這是因為快速的雜湊函式使得暴力攻擊變得更加容易和廉價。因此,傳統的加密雜湊函式(如BLAKE2)並不適合用於密碼雜湊。

金鑰衍生函式(KDFs)

金鑰衍生函式(KDFs)是一類特殊的函式,旨在消耗大量的計算資源、記憶體或兩者兼而有之。這使得KDFs成為密碼雜湊的最佳工具。KDFs接受一個訊息(密碼)、鹽和至少一個組態引數,後者用於調整資源消耗。這意味著你可以控制KDF的執行速度。

密碼基礎金鑰衍生函式2(PBKDF2)

PBKDF2是一種流行的密碼基礎金鑰衍生函式,設計用於包裝和遞迴呼叫雜湊函式。它的迭代次數和雜湊函式都是可組態的。實際應用中,PBKDF2通常包裝HMAC函式,後者又包裝SHA-256。

實作PBKDF2的效能基準測試

以下是一個簡單的Python指令碼,使用PBKDF2包裝HMAC-SHA256,測試其效能:

import hashlib
import timeit

def test_pbkdf2():
    # 設定迭代次數
    iterations = 100000
    
    # 定義訊息和鹽
    message = b"password"
    salt = b"salt"
    
    # 包裝HMAC-SHA256
    def pbkdf2_hmac_sha256(message, salt, iterations):
        return hashlib.pbkdf2_hmac("sha256", message, salt, iterations)
    
    # 測試函式
    def test():
        return pbkdf2_hmac_sha256(message, salt, iterations)
    
    # 記錄時間
    time = timeit.timeit(test, number=10)
    
    return time

# 執行測試
time = test_pbkdf2()
print(f"PBKDF2包裝HMAC-SHA256耗時:{time}秒")

這個指令碼測試了PBKDF2包裝HMAC-SHA256的效能,設定了100,000次迭代。結果顯示,PBKDF2的執行速度遠慢於傳統的雜湊函式,這使得暴力攻擊變得更加困難和昂貴。

密碼雜湊演算法PBKDF2的效能評估

簡介

PBKDF2(Password-Based Key Derivation Function 2)是一種廣泛使用的密碼雜湊演算法,旨在保護密碼安全。它的設計目的是使得密碼的雜湊過程更加耗時和耗資源,從而增加攻擊者的難度。這篇文章將探討PBKDF2的效能評估,包括其基本原理、實作細節和效能測試。

PBKDF2的基本原理

PBKDF2的核心思想是使用一個密碼、鹽值(salt)和迭代次數(iteration)作為輸入,生成一個固定長度的雜湊值。鹽值是一個隨機生成的位元組串,用於增加密碼的複雜度和防止彩虹表攻擊。迭代次數則控制了雜湊過程的耗時程度。

實作細節

以下是PBKDF2的實作細節:

import hashlib
import secrets
import sys

def pbkdf2_sha256(password, salt, iterations):
    """
    實作PBKDF2的SHA256雜湊演算法
    """
    hash_value = hashlib.pbkdf2_hmac('sha256', password, salt, iterations)
    return hash_value.hex()

# 引數化迭代次數
iterations = int(sys.argv[1])

# 測試函式
def test():
    message = b'password'
    salt = secrets.token_bytes(16)
    hash_value = pbkdf2_sha256(message, salt, iterations)
    print(hash_value)

if __name__ == '__main__':
    # 執行測試10次
    seconds = timeit.timeit('test()', number=10, globals=globals())
    print('Seconds elapsed: %s' % seconds)

效能測試

為了評估PBKDF2的效能,我們可以使用時間測試工具timeit來測量執行時間。以下是執行命令和輸出結果:

$ python pbkdf2.py 260000

輸出結果顯示了10次執行的總耗時。這個結果可以用來評估PBKDF2的效能和安全性。

密碼雜湊與時間複雜度

在密碼學中,密碼雜湊是一種常見的技術,用於保護使用者的密碼安全。密碼雜湊的基本思想是將明文密碼轉換為一串固定長度的雜湊值,從而使得即使攻擊者獲得了雜湊值,也無法逆向推匯出原始密碼。

從系統安全形度出發,本文深入探討了密碼變更、重置、雜湊、驗證和儲存等關鍵環節。分析了Django內建機制和自訂方法,例如使用PasswordChangeViewPasswordResetView以及自訂驗證器PassphraseValidator,有效提升密碼管理的安全性。同時,本文也指出了密碼儲存的常見誤區,強調了雜湊演算法的重要性,並以PBKDF2為例,闡述了其原理和效能測試方法,以及如何透過調整迭代次數來平衡安全性和效能。然而,單純提高迭代次數並非解決安全性的萬靈丹,仍需考量硬體資源的限制以及潛在的旁路攻擊風險。展望未來,隨著量子計算的發展,現有的雜湊演算法可能面臨新的挑戰,探索抗量子密碼學演算法將成為密碼安全領域的關鍵方向。玄貓認為,採用縱深防禦策略,結合多因素驗證、入侵偵測等手段,才能構建更完善的密碼安全體系。對於重視安全性的系統,建議定期更新密碼策略,並密切關注密碼學領域的最新發展,才能有效防禦不斷演變的攻擊威脅。