$30 off During Our Annual Pro Sale. View Details »

Djangoのパスワードハッシュアルゴリズムで_PyramidのWebアプリケーション作った.pdf

 Djangoのパスワードハッシュアルゴリズムで_PyramidのWebアプリケーション作った.pdf

mizzsugar

May 19, 2020
Tweet

More Decks by mizzsugar

Other Decks in Programming

Transcript

  1. Djangoのパスワードハッシュア
    ルゴリズムで
    PyramidのWebアプリケーショ
    ン作った
    2020-05-18 mizzsugar0425 @BPLL

    View Slide

  2. お前誰よ
    ● みずきと申します。
    ● Twitter @mizzsugar0425
    ● PythonでWebサービス開発してます。(本業Django, 副業Pyramid)
    ● PyConJPのCfPの締切に焦ってます(;´Д`)

    View Slide

  3. 今日話す話の対象となる人
    ● ある程度Djangoを使ったWebアプリケーションまたはサービスの開発をできる

    View Slide

  4. 今日話すこと
    ● Djangoデフォルトパスワードアルゴリズムの説明(ざっくり)
    ● Djangoのソースコードを一部適用させたのでライセンスの話
    ● 作ったアプリでどうやってパスワードアルゴリズムを適用させたか
    ● 爆誕させたもの↓
    https://github.com/mizzsugar/pyramid-app-with-django-password-hash

    View Slide

  5. きっかけ

    View Slide

  6. 最近思うこと

    View Slide

  7. Djangoは制約が多すぎて辛い

    View Slide

  8. そうだ、リプレースすればいいんだ(雑)

    View Slide

  9. いろいろやらないといけないこ
    とあるけど・・・
    migrationファイルどーするの
    ログインユーザーのトークンとか
    ORMで発行したクエリ
    その他Djangoにまかせた何か

    View Slide

  10. Djangoデフォルトの
    パスワードハッシュアルゴリズムを
    他のWebフレームワークで使うには
    どうすれば?

    View Slide

  11. Djangoのパスワードの仕組みたどってみた
    from django.contrib.auth.models import User
    user = User.objects.create(email='sample.example.com')
    user.set_password('password') # パスワードハッシュ
    user.save()
    # return True
    user.check_password('password') # パスワードチェック

    View Slide

  12. check_password, set_passwordが
    エントリポイントらしいぞ

    View Slide

  13. たどったら
    django.contrib.auth.hashersモジュールの
    check_password(上), make_password(下) にたどり着いた。
    https://github.com/django/django/blob/master/django/contrib/auth/hashers.
    py#L30
    https://github.com/django/django/blob/master/django/contrib/auth/hashers.
    py#L64

    View Slide

  14. 色んなハッシュアルゴリズム使えるよう
    settings.pyのPASSWORD_HASHERSで使いたいパスワードアルゴリズムを定義
    PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    ]
    デフォルトのsettings.pyのPASSWORD_HASHERS
    https://docs.djangoproject.com/ja/3.0/topics/auth/passwords/#how-django-stores-passwords

    View Slide

  15. デフォルトではどのアルゴリズムが?
    PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    ]
    このリストを読み込んで一番上のアルゴリズムのクラスを使う仕組み。
    デフォルトだとdjango.contrib.auth.hashersモジュールの
    PBKDF2PassswordHasherクラスを使うよう。

    View Slide

  16. これを適用するには?
    PBKDF2PassswordHasherクラスをコピペするのが楽だけど
    ライセンス大丈夫?

    View Slide

  17. Djangoは3-clause BSD-3-Clauseライセンス
    以下の条件下なら修正あり、なしに関わらずソースコードの再配布OK
    1. ソースコードの再配布は、上記の著作権表示、ここに列挙された条件、および下記の免責条項を保
    持すること。
    2. バイナリ形式の再配布は、上記の著作権表示、ここに列挙された条件、および下記の免責条項は、ド
    キュメントまたは他の資料で配布すること。
    3. このソフトウェアのコントリビューター (貢献者)の名前は、特定の書面による事前の許可なしに、このソ
    フトウェアから派生した製品の保証または販売促進のために使用してはいけない。
    https://opensource.org/licenses/BSD-3-Clause

    View Slide

  18. リポジトリにDjangoライセンス明記
    https://github.com/mizzsugar/pyramid-app-with-django-password-hash/blob/
    master/LICENSE.Django

    View Slide

  19. 今回作ったリポジトリ自体のライセンス
    ● BSD-3-Clauseにした
    ● Django自身のライセンスよりもゆるくするのは怖いのでやめといた

    View Slide

  20. 今回作ったもののディレクトリ構成
    ● Djangoから取り入れた部分はビジネスロジックとは切り離してライブラリとして導
    入する方針
    ● ビジネスロジックではmake_password, check_passwordを呼び出すだけにす

    View Slide

  21. ├── LICENSE
    ├── LICENSE.Django
    ├── README.rst
    └── application
    ├── Makefile
    ├── migrations
    │ └── 0001_core.sql
    ├── mypy.ini
    ├── openapi.yaml
    ├── poetry.lock
    ├── sample
    │ ├── __init__.py
    │ ├── application.py
    │ ├── bootstrap.py
    │ ├── domain
    │ │ ├── __init__.py
    │ │ └── authentication.py(viewで呼び出す認証処理書いてる )
    │ │
    │ ├── libs
    │ │ ├── __init__.py
    │ │ ├── crypto.py(make_password, check_passwordに必要)
    │ │ ├── encoding.py(make_password, check_passwordに必要)
    │ │ ├── module_loading.py(make_password, check_passwordに必要)
    │ │ └── password.py(ここにmake_password, check_passwordがある)
    │ ├── repository
    │ ├── scripts
    │ ├── views
    │ └── wsgi.py
    └── tests
    ※一部省略しています。

    View Slide

  22. パスワードチェックの実装
    def sign_in(self, draft: sample.dto.SignIn) -> sample.domain.dto.User:
    try:
    user = self._repository.authentication.fetch_by_email(draft.email) # DBアクセス
    except sample.repository.exceptions.NotFoundError:
    raise sample.domain.exceptions.InvalidCredentialError()
    if not sample.libs.password.check_password(draft.password, user.password):
    raise sample.domain.exceptions.InvalidCredentialError()
    return sample.domain.converters.User.from_repository(user)

    View Slide

  23. パスワードを暗号化する実装
    def register_user(self, draft: sample.domain.dto.DraftUser) -> None:
    password = sample.libs.password.make_password(draft.password) # パスワードハッシュ
    try:
    self._repository.authentication.register_user(
    sample.repository.dto.DraftUser(email=draft.email, password=password)) # DBに登録
    except sample.repository.exceptions.ConflictError:
    raise sample.domain.exceptions.AlreadyRegisteredError()

    View Slide

  24. これからしたいこと
    ● Djangoから得た部分のTypeHint
    ● CIの設定
    ● パスワードのところもうちょっとテスト追加
    ● iterationの回数の増加タイミング見極め
    ● ログインした際のトークン発行

    View Slide

  25. ありがとうございました。

    View Slide