2015-02-23 47 views
5

我一直在探索Twin-Bcrypt JavaScript庫,發現一個奇怪的東西。在某一時刻,我在服務器端用PHP base64_encode(openssl_random_pseudo_bytes(16))製作了自己的鹽,並在TwinBcrypt.hash()函數中使用它,該函數響應由於庫中規則的模式不匹配而導致salt無效。因此,模式是:JS Twin-Bcrypt鹽圖案

var SALT_PATTERN = /^\$2[ay]\$(0[4-9]|[12][0-9]|3[01])\$[.\/A-Za-z0-9]{21}[.Oeu]/; 

和它看起來罰款我的鹽,除了一兩件事 - 到底是什麼 - [.Oeu]

我的第一個問題是,爲什麼他們從鹽期待與結束,或Ø,或ē,或ü?據我所知openssl_random_pseudo_bytes()生成安全CSPRNG,但由於模式JS庫不想接受它。

第二個問題 - 鹽是否有任何安全原因以/[.Oeu]/模式結束?

我會非常感謝任何幫助,因爲沒有多少關於它的信息。

回答

4

我不知道bcrypt真的很好,但現在看來,雙Bcrypt預計salt參數,包括完整的類型標籤(2a/2y/2x),成本參數,實際的加密鹽值。 (我相信這是爲了符合其他庫的期望。)加密salt值只是salt參數字符串的最後22個字符,它們表示128位值。

要真正解決你的問題,你需要做兩兩件事:

  1. 前綴的鹽與$2y$10$,使其有一個類型標籤和成本參數。

  2. 將您的PHP base64_encode結果映射到bcrypt的非標準base64值。作爲參考,值:

    Standard: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/ 
    bcrypt: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
    

    如果你只想做一個標準的base64成brcypt-的base64字符串,可以用.取代所有+,但是這將導致不同的值(因爲標準+62,而.0,並且所有其他值也被抵消)。如果您想要一個與原始值相同的brypt字符串,則需要用每個字符替換它的bcrypt。

    您可能還需要從標準字符串中刪除尾部=(如果存在)。


的額外信息:爲什麼必須將鹽與[.Oeu]結束?

bcrypt中的salt是128位。每個base64字符傳遞6位信息。這意味着21個base64字符可以平均傳送126位。最後2位必須在最後的第22個字符中編碼。由於該字符僅由2位定義,因此它只能有4個可能的值。

當我們檢查brypt以base64字符庫,我們可以看到:

./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

從零算起,我們看到,這些值將出現在indicies:

. => 0 = 000000 
O => 16 = 010000 
e => 32 = 100000 
u => 48 = 110000 

因此,那些後二位設置最終字符的高端位。

+0

這應該被添加到Wiki。非常感謝! – Nevertheless 2015-02-23 14:04:03