バイクリプトステップバイステップ



郵便Bcrypt Step by Step 初登場Qvault .
bcryptはaであるkey derivation function , これは遅いと考えられるhash function . その目的は、ゆっくりと一定のサイズ、決定論的、予測不可能な出力に入力データの一部を変換することです.一般的なユースケースは、パスワードをNビット暗号化キーに変換することです.
ヒアアットQvault, 我々は、セキュリティシステムでbcryptを使用します.bcryptは非常に人気のあるパスワードハッシュ機能ですので、現在のところ我々の実装を教えるハッシュ関数ですPractical Cryptography コース.

bcryptのように見えます


mypassword 123でbcryptを使用すると次のようになります.
**_myPassword123_** ->$2y$12$vUw4OU4EAl4w4vC6/lA33OtDSYGhiIdekdT9iOoSs9/ckwrffaEui
この出力を使用すると、将来のハッシュに対して、元のデータが一致するかどうかを比較できます.

なぜ直接パスワードを比較しない?


Web開発では、ユーザのパスワードをプレーンテキストに保存するのは安全です.攻撃者がサーバーのデータベースへのアクセスを得るなら、彼らは生の電子メール/パスワード組合せを見つけることができて、彼らを他のサイトで同じユーザーを攻撃するために使うことができました.
少なくとも、ユーザのパスワードをハッシュする必要がありますが、ハッシュ関数SHA-2 そして、MD 5はあまりに速く、安全であるためにあります.KDFのようなBcryptを使用すると、それは計算的に高価で遅いため、高速ハッシュのセキュリティ上の利点を提供します.攻撃者が速いアルゴリズムで作られるパスワードハッシュのデータベースへのアクセスを得るならば、彼らが異なる入力を推測して、出力がマッチするかどうか見ることによってハッシュを「逆」にするのは簡単です.
たとえば、攻撃者がデータベースに次のエントリを見つけたとしましょう.
[email protected] 5906ac361a137e2d286465cd6588ebb5ac3f5ae955001100bc41577c3d751764
以下のような一般的なパスワードをハッシュしてみることができます.
password1 ->0b14d501a594442a01c6859541bcb3e8164d183d32937b851835442f69d5c94epassword2 ->6cf615d5bcaac778352a8f1f3360d23f02f34ec182e259897fd6ce485d7870d4password3 -> 5906ac361a137e2d286465cd6588ebb5ac3f5ae955001100bc41577c3d751764
パスワードpassword3 , 一致するハッシュを生産!今攻撃者は知っている[email protected] はパスワードを使用しますpassword3 他のサイトで、他のアカウントをハック行くことができます.攻撃者がすぐに多くのハッシュを計算することができるので、これは可能です.
遅いkdfのようなbcryptはこの問題を解決します.

bcrypt出力形式


$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy\_\_\_/\_\_/\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/Alg Cost Salt Hash
  • 2a : hashアルゴリズムの識別子( bcrypt )
  • 10 : コストファクター10 = 1024ラウンド展開
  • N9qo8uLOickgx2ZMRZoMye : 16バイト( 128ビット)塩、22文字にエンコードされたbase 64
  • IjZAgcfl7p92ldGxad68LJZdL17lhWy : 24バイト( 192ビット)ハッシュ
  • ダイレクトフロムWikipedia

    bcryptは一歩一歩説明した


    bcryptは次のような擬似コードで可視化できます:
    func bcrypt(cost int, salt [16]byte, password [72]byte) (hash string) {
        // Initialize Blowfish state with expensive key setup algorithm
        // This is the slow part of the algorithm
        pEighteenSubkeys, sFourSubBoxes := expensiveBlowfishSetup(cost, salt, password)
    
        // Repeatedly encrypt the text "OrpheanBeholderScryDoubt" 64 times
        // 24 bytes = three 64-bit blocks
        ctext := "OrpheanBeholderScryDoubt"
        for i := 0; i < 64; i++ {
            // Encrypt using standard Blowfish in ECB mode
            ctext = encryptECB(pEighteenSubkeys, sFourSubBoxes, ctext)
        }
    
        // return the version, cost, salt, and ctext in the proper format
        return "$2a${cost}${salt}{ctext}"
    }
    
    ご覧のように、BcryptはBlowfish 暗号.簡単に言えば、BcryptはBlowfish暗号化と組み合わせる高価なキー拡張です.
    The expensiveBlowfishSetup 関数は擬似コードに従って理解できる:
    // pEighteenSubkeys: array of 18 subkeys
    // sFourSubBoxes: Four substitution boxes
    // Each S-Box is a 256-length array of uint32
    func expensiveBlowfishSetup(cost int, salt [16]byte, password [72]byte) (pEighteenSubkeys [18]uint32, sFourSubBoxes [4][256]uint32) {
        // Initialize arrays
        pEighteenSubkeys := [18]uint32
        sFourSubBoxes := [4][256]uint32
    
        // Fill pEighteenSubkeys and sFourSubBoxes with the hex digits of pi 
        // This initial state works as in the original Blowfish algorithm
        // it populates the P-array and S-box entries with the fractional part of pi in hexadecimal
        pEighteenSubkeys = fillWithPi(pEighteenSubkeys)
        sFourSubBoxes = fillWithPi(sFourSubBoxes)
    
        // Permutate P and S based on the password and salt
        pEighteenSubkeys, sFourSubBoxes = expandKey(pEighteenSubkeys, sFourSubBoxes, salt, password)
    
        // This is the "Expensive" part of the "Expensive Key Setup"
        // Otherwise the key setup would be identical to Blowfish
        // Expand the key an exponentially increasing number of times
        // depending on the cost factor
        for i := 0; i < math.Pow(2, cost); i++ {
            pEighteenSubkeys, sFourSubBoxes = expandKey(pEighteenSubkeys, sFourSubBoxes, 0, password)
            pEighteenSubkeys, sFourSubBoxes = expandKey(pEighteenSubkeys, sFourSubBoxes, 0, salt)
        }
    
        return pEighteenSubkeys, sFourSubBoxes
    }
    
    The expandKey function は、cost パラメータThe expandKey 関数は以下の擬似コードで説明する:
    func expandKey(pEighteenSubkeys [18]uint32, sFourSubBoxes [4][256]uint32, salt [16]byte, password [72]byte) (
        pEighteenSubkeys [18]uint32, sFourSubBoxes [4][256]uint32
        ) {
    
        // Mix password into the pEighteenSubkeys array
        // by XORing password with subkeys
        for i := 0; i < 18; i++{
            // treat the password as cyclic, XOR 32 bit chunks of password with subkeys
            pEighteenSubkeys[i] ^= password[i % 18]
        }
    
       // Treat the 128-bit salt as two 64-bit halves 
       saltHalf[0] = salt[0:63]
       saltHalf[1] = salt[64:127]
    
       // Initialize an 8-byte (64-bit) buffer with all zeros.
       block := [8]byte
    
       // Mix internal state into P-boxes   
       for i := 0; i < 9; i++ {
          // XOR 64-bit block with a 64-bit salt half
          // Each iteration alternating between saltHalf[0], and saltHalf[1]
          block ^= saltHalf[(i-1) mod 2]
    
          // Encrypt block using current key schedule with blowfish block encryption
          block = Encrypt(pEighteenSubkeys, sFourSubBoxes, block)
    
          // Split block and use as new subkeys
          pEighteenSubkeys[2*i] = block[0:31]
          pEighteenSubkeys[2*i + 1] = block[32:63]
       }
    
       // Mix encrypted state into the internal S-boxes of state
       for i := 0; i < 4; i ++ {
          for j := 0; j < 127; j++ {
            // Encrypt block using blowfish block encryption
            // where salt[i] is 64 bit chunks
            block = Encrypt(pEighteenSubkeys, sFourSubBoxes, block ^ salt[i])
            sFourSubBoxes[2*i] = block[0:31]
            sFourSubBoxes[2*i + 1] = block[32:63]
          }
        }
        return pEighteenSubkeys, sFourSubBoxes
    }
    
    goのようなもっとリアルなプログラミング構文を使って疑似コードの詳細を視覚化するのに役立ちます.それがあなたを助けないならばWikipedia ここのページ.

    読書ありがとう!


    あなたがどんな質問またはコメントをするならば、さえずりの上で我々について来てください
    コーディングコースのようなゲームを取るQvault Classroom
    Subscribe より多くの教育記事のための我々の会報へ