パスワードの暗号化


ユーザのパスワードをそのままDBに保存するのは危険です。そのため、暗号化ストレージを行う必要がある。

Hash Function


プレイヤーのパスワードを123とします.ハッシュ関数は、"123"を"8 Qui 2 rgkim 0 cAUH 0 uTLKKASKR 2 X 51 su"に置き換える関数です.
仮定的.実際に変更した値とは異なります.

特長


  • 同じ入力値に対して、常に同じ結果値が得られます.
    「123」と入力すると、常に「8 Qui 2 rgkim 0 cAuh 0 uTLkKASKR 2 X 51 su」の結果値があります.

  • 入力値が少し変わると、結果値が非常に異なります.
    「123」の出力値は「1234」の出力値とは大きく異なる.

  • ハッシュ関数は一方向関数です.
    「123」と入力すると「8 Qui 2 rgkim 0 cAuh 0 uTLkKASKR 2 X 51 su」が得られますが、ドメインは成立しません.
  • 変更した値をハッシュ関数でDBに保存するのが安全です.

    Key Stretching, Salt


    しかし,ハッシュ関数のみを用いてパスワードを安全に格納することはできない.フィーチャー1号のためGoogleでハッシュ関数を検索して123を入力すると、そのハッシュ関数の数値を直接知ることができます.これにより、ハッシュ関数が入力した結果値が「Rainbowテーブル」と呼ばれるリストがあります.

  • KeyStretchingは多重回転ハッシュ関数の動作である.
    たとえば、3回実行するとします.
    "123" ---> "8QuI2rgKIm0cAuH0uTLkKKASkR2X51su" (1번)
    "8QuI2rgKIm0cAuH0uTLkKKASkR2X51su" ---> "Nd07AoqqlBtozMMU3A6ABW4WgJLeHSub" (2번)
    "Nd07AoqqlBtozMMU3A6ABW4WgJLeHSub" ---> "2SGApMywq2vbfpJ0XSjLQRfROcFcWeLv" (3번)
    最終結果値は"2SGApMywq2vbfpJ0XSjLQRfROcFcWeLv"です.もちろん、Rainbow表で調べられますが、調べるにはかなり時間がかかります.

  • Saltは「ユーザが入力したパスワード+任意の値」をハッシュ関数として値を入力する方法である.
    ユーザが「123」のパスワードを入力したとすると、saltは任意の値として「9 XoRMVqU 3 jUJU 6 aIECu 9 uD 9 WHdTUAJ 7」を与える.
    では、ハッシュ関数の"1239XoRVMqU3jUjUs6aIECu9uD9WHdtUAJ7"が入力値に入ります.Rainbowテーブルが123の結果値を持っていても,任意の値により推定が困難となる.
  • Bcrypt


    keystretchingもsaltも使用してハッシュ関数に変換したらどうなりますか?分かりにくいでしょう?bcryptはこの2つを使用してパスワードを暗号化します.

    使用方法

    userSchema.pre("save", async function () {
      if (this.isModified("password")) {
        this.password = await bcrypt.hash(this.password, 5);
      }
    });

    その他


    preは、データベースに格納される前に実行されるmongoseミドルウェアである.上記のコードの場合は、Document.prototype.save()を実行するときにpre関数を呼び出します.async/awaitを使用するとnext()を省略できます.

    Reference


  • bcrypt

  • hash, salt

  • mongoose