Как мне справиться с засолкой хэша пароля в Vapor 3? - PullRequest
0 голосов
/ 07 января 2019

Я создаю базовую настройку аутентификации, аналогичную той, которая используется в шаблоне Vapor auth-template здесь ). У меня все настроено так же, как в шаблоне.

Однако я бы хотел добавить соль. Я могу создать соль для пользователя при создании:

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)
}

Я хочу, чтобы соль генерировалась случайным образом для каждого пользователя и сохранялась в базе данных как отдельный столбец из хешированного пароля, который будет использоваться позже во время аутентификации.

Существует ли стандартизированный способ обработки холя пароля в Vapor 3?

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Вы хэшируете пароль, используя BCrypt. BCrypt уже является частью зависимостей Vapor.

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

Это будет хэшировать строку «пар», используя случайно сгенерированную соль, со сложностью 4. Выбор стоимости субъективен и произвольн, но рекомендуется, чтобы реальные безопасные приложения имели коэффициент затрат выше 10-12. Если вам не нравится, как соль генерируется случайным образом BCrypt, и вы хотите создать свою собственную соль, вы можете указать ее для хеш-функции, которая имеет следующую подпись:

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)
0 голосов
/ 07 января 2019

В Vapor работает так, что каждый хеш BCrypt имеет уникальную соль, которая сохраняется с паролем в базе данных. Функции по умолчанию BCrypt в Vapor ожидают этого.

Если вы хотите пойти по другому пути, взгляните на функцию хеширования пароля, которая требует соли. Затем вы можете сохранить его в своем собственном поле и получить его, когда вы подтвердите пароль. Честно говоря, я бы сказал, чтобы просто использовать значения по умолчанию, если у вас нет особых причин не

...