私はフレームワークとパスワードハッシュをプレイするのが少し新しいです。パスワードをハッシュ化するための解決策をいくつか見つけようとしたところ、BCrypt が見つかりました。パスワードをハッシュするのに十分だと思いますか。それがよければ、どうすれば play フレームワークで動作させることができますか? (私は play 2.1.3 を使用しています) ありがとう!
4 に答える
これは、BCrypt を使用してパスワードをハッシュする、私が作成した Play Java プロジェクトのサンプルです。 newUser() および signIn() アクションを参照してください。
https://github.com/jroper/play-demo-twitbookplus/blob/master/app/controllers/UserController.java
Scalaでも同様のことができます。要約すると、Build.scala の依存関係に jbycrpt を追加します。
val appDependencies = Seq(
"org.mindrot" % "jbcrypt" % "0.3m"
)
次に、これを使用してパスワードをハッシュします。
String passwordHash = BCrypt.hashpw(password, BCrypt.gensalt());
そして、これを使用してパスワードを確認します:
BCrypt.checkpw(password, passwordHash)
アップデート (2020)
最近の私のプロジェクトでは、BCrypt を使用しなくなり、PBKDF2 ハッシュを使用しています。これには、追加の依存関係を必要としないという利点がありますが、かなり多くのコードを記述して手動でソルトを管理する必要があるという欠点があります。BCrypt には、異なる実装が互いの出力を正確に消費できないという問題もあり、実装によっては長いパスワードを切り捨ててしまうこともありますが、これは非常に悪いことです。より多くのコードですが、私はこのアプローチが気に入っています。なぜなら、より多くの制御が可能になり、物事がどのように機能しているかを透過的に正確に示し、ハッシュアルゴリズムと入力パラメーターの推奨事項が絶えず変化するため、時間の経過とともに物事を簡単に更新できるからです。
とにかく、これが私が使用するコードです。ソルトと使用される反復回数を格納します (ベストプラクティスが推奨するように、時間の経過とともにこれらを増やすことができるようにするため)、コロンで区切られたハッシュ値:
val DefaultIterations = 10000
val random = new SecureRandom()
private def pbkdf2(password: String, salt: Array[Byte], iterations: Int): Array[Byte] = {
val keySpec = new PBEKeySpec(password.toCharArray, salt, iterations, 256)
val keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
keyFactory.generateSecret(keySpec).getEncoded
}
def hashPassword(password: String, salt: Array[Byte]): String = {
val salt = new Array[Byte](16)
random.nextBytes(salt)
val hash = pbkdf2(password, salt, DefaultIterations)
val salt64 = Base64.getEncoder.encodeToString(salt)
val hash64 = Base64.getEncoder.encodeToString(hash)
s"$DefaultIterations:$hash64:$salt64"
}
def checkPassword(password: String, passwordHash: String): Boolean = {
passwordHash.split(":") match {
case Array(it, hash64, salt64) if it.forall(_.isDigit) =>
val hash = Base64.getDecoder.decode(hash64)
val salt = Base64.getDecoder.decode(salt64)
val calculatedHash = pbkdf2(password, salt, it.toInt)
calculatedHash.sameElements(hash)
case other => sys.error("Bad password hash")
}
}
私の実際のコードはもう少し複雑です。バージョン管理されたマジック ワードを最初のコンポーネント ( ph1:
) として含めています。つまり、出力値にエンコードされていないハッシュ アルゴリズムやその他の入力パラメーターを変更する場合は、マジック ワードを に更新してこれらのハッシュをエンコードすると、古いハッシュと新しいハッシュph2:
の両方を検証するコードを作成できます。ph1
ph2
BCrypt は、パスワードのハッシュに適しています。Silhouetteを使用し、パスワード プラグインにBCrypt パスワード ハッシャーを使用します。
このプロジェクトは、jbcrypt https://github.com/t3hnar/scala-bcryptの優れた scala ラッパーを提供します- 過去に使用したことがあり、うまく機能します。
最近の bcrypt t3hnar ライブラリ バージョン 4.1 を Play フレームワークと連携させるための手順は次のとおりです。
依存関係を build.sbt に追加します。
libraryDependencies += "com.github.t3hnar" %% "scala-bcrypt" % "4.1"
プロジェクトに Hash オブジェクトを追加します。
// Reference: https://github.com/t3hnar/scala-bcrypt
package utilities
import com.github.t3hnar.bcrypt._
import play.api.Logging
import scala.util.Success
import scala.util.Failure
object Hash extends Logging {
private val log = Log.get
def create(value: String): String = {
log.debug("Encrypting a value")
// Creating a salted hash
val salt = generateSalt
val hash = value.bcrypt(salt)
// return hashed value
hash
}
def validate(value: String, hash: String): Boolean = {
// Validating the hash
value.isBcryptedSafe(hash) match {
case Success(result) => { // hash is valid - correct salt and number of rounds
log.trace("Hash is safe")
if (result) log.trace("Test hash matches stored hash") else log.trace("Test hash does not match stored hash")
result // true if test hash matches the stored has, false if it does not
}
case Failure(failure) => {
// Hash is invalid
log.trace("Hash is not safe")
false
}
}
}
}
使用例:
// Password hashing
val hash = Hash.create(password)
// Password validation
def authenticate(email: String, password: String): Option[User] = {
log.debug(s"Authenticating user: $email")
// Get user
read(email) match {
case Some(user) => {
// Compare password with the hashed value
if (Hash.validate(password, user.hash)) Some(user) else None
}
case None => {
// Cannot find user with this email
log.trace(s"User not found")
None
}
}
}
ハッシュ ユーティリティの例: https://github.com/LineDrop/play-scala-web-application/blob/master/app/utilities/Hash.scala
ユーザー モデルの例: https://github.com/LineDrop/play-scala-web-application/blob/master/app/models/User.scala