簡體   English   中英

如何在Vapor 3中處理密碼哈希?

[英]How do I handle salting a password hash in Vapor 3?

我正在構建一個基本的身份驗證設置,類似於在Vapor的auth-template模板中使用它(從這里開始 )。 我將所有內容設置為與模板中相同的方式。

但是,我想加鹽。 我可以在創建時為用戶生成一個salt:

static func create(_ req: Request, newUserRequest user: CreateUserRequest) throws -> Future<User.Public> {
    return User.query(on: req).filter(\.username == user.username).first().flatMap { existingUser in
        guard existingUser == nil else {
            throw Abort(.badRequest, reason: "A user with the given username already exists.")
        }

        guard user.password == user.passwordVerification else {
            throw Abort(.badRequest, reason: "Given passwords did not match.")
        }

        let count = 16
        var pw_salt_data = Data(count: count)
        let _ = pw_salt_data.withUnsafeMutableBytes { mutableBytes in
            SecRandomCopyBytes(kSecRandomDefault, count, mutableBytes)
        }
        let pw_salt = try BCrypt.hash(pw_salt_data.base64EncodedString())

        let pw_hash = try BCrypt.hash(pw_salt + user.password)

        return User(id: nil, username: user.username, pw_hash: pw_hash, pw_salt: pw_salt, email: user.email).save(on: req).toPublic()
    }
}

但是在登錄期間執行身份驗證時無法檢索該鹽:

static func login(_ req: Request) throws -> Future<UserToken> {
    let user = try req.requireAuthenticated(User.self)
    let token = try UserToken.create(userID: user.requireID())
    return token.save(on: req)
}

我希望為每個用戶隨機生成salt,並將其作為與散列密碼分開的列存儲在數據庫中,以便稍后在身份驗證期間使用。

有沒有一種標准化的方法來處理在Vapor 3中腌制密碼哈希?

它在Vapor中的工作方式是每個BCrypt哈希都有一個唯一的鹽,它與數據庫中的密碼一起保存。 Vapor中的BCrypt默認功能期待這一點。

如果你想沿着不同的路線走下去,看一下哈希密碼的函數 - 這需要一個鹽。 然后,您可以將其保存在自己的字段中,並在驗證密碼時進行檢索。 老實說,我會說只是使用默認值,除非你有一個非常具體的理由不這樣做

您使用BCrypt散列密碼。 BCrypt已經是Vapor依賴項的一部分。

BCrypt.hash("vapor", cost: 4)

這將使用隨機生成的鹽散列字符串“vapor”,復雜度為4.選擇成本是主觀的和隨意的,但建議現實世界的安全應用程序應具有10-12以上的成本因子。 如果您不喜歡BCrypt隨機生成的鹽,並且您想生成自己的鹽,則可以向哈希函數提供salt,該函數具有以下簽名:

public func hash(_ plaintext: LosslessDataConvertible, cost: Int = 12, salt: LosslessDataConvertible? = nil) throws -> String 

文檔說如果手動提供,鹽必須是16字節。 這是一個示例哈希:

$2a$04$/nqhWqplnughhq6mlKmi8.raprxoG/dczY8kdbOKm.zC5sPu.2IBi

正如您所看到的,它包括輔助信息,例如復雜性,算法類型和鹽,以及進行驗證所需的一切。 如果您提供了自己的鹽,它也將成為最終哈希的一部分,您無需單獨提供它。 您可以按照以下說明進行驗證。

try BCrypt.verify("vapor", created: hashedPasswordSavedInDatabase)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM