From 16a00b52553fadfe23f6432afde479223e966581 Mon Sep 17 00:00:00 2001 From: RockfordWei Date: Tue, 16 Jan 2018 16:15:55 -0500 Subject: [PATCH 1/2] Fixing ISS-570 By applying a self-salt generation method with AES128 encryption, the password storage security should be improved from rainbow table attack. --- .../Schema/Account.swift | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Sources/PerfectLocalAuthentication/Schema/Account.swift b/Sources/PerfectLocalAuthentication/Schema/Account.swift index b28ae18..f8d1526 100644 --- a/Sources/PerfectLocalAuthentication/Schema/Account.swift +++ b/Sources/PerfectLocalAuthentication/Schema/Account.swift @@ -10,6 +10,7 @@ import StORM import PostgresStORM import SwiftRandom import PerfectSMTP +import PerfectCrypto public class Account: PostgresStORM { public var id = "" @@ -107,12 +108,24 @@ public class Account: PostgresStORM { id = _r.secureToken } + public static func makeShadow(from: String) -> String? { + if let hashData = from.digest(.sha384) { + let hashKeyData:[UInt8] = hashData[0..<32].map {$0} + let ivData:[UInt8] = hashData[32..<48].map {$0} + let data:[UInt8] = from.utf8.map { $0 } + if let x = data.encrypt(.aes_128_cbc, key: hashKeyData, iv: ivData), + let y = x.encode(.base64), + let z = String(validatingUTF8: y) { + return z + } + } + return nil + } + public func makePassword(_ p1: String) { - if let digestBytes = p1.digest(.sha256), - let hexBytes = digestBytes.encode(.hex), - let hexBytesStr = String(validatingUTF8: hexBytes) { - password = hexBytesStr - } + if let shadow = Account.makeShadow(from: p1) { + password = shadow + } } public func isUnique() throws { @@ -187,12 +200,9 @@ public class Account: PostgresStORM { // Register User public static func login(_ u: String, _ p: String) throws -> Account { - if let digestBytes = p.digest(.sha256), - let hexBytes = digestBytes.encode(.hex), - let hexBytesStr = String(validatingUTF8: hexBytes) { - + if let shadow = Account.makeShadow(from: p) { let acc = Account() - let criteria = ["username":u,"password":hexBytesStr] + let criteria = ["username":u,"password":shadow] do { try acc.find(criteria) if acc.usertype == .provisional { From 7ecbea1c78f9f1546bc624fe5aa3b4a22feadf6b Mon Sep 17 00:00:00 2001 From: RockfordWei Date: Wed, 17 Jan 2018 11:50:08 -0500 Subject: [PATCH 2/2] Adding salt. --- .../Schema/Account.swift | 49 +++++++------------ 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/Sources/PerfectLocalAuthentication/Schema/Account.swift b/Sources/PerfectLocalAuthentication/Schema/Account.swift index f8d1526..137da5b 100644 --- a/Sources/PerfectLocalAuthentication/Schema/Account.swift +++ b/Sources/PerfectLocalAuthentication/Schema/Account.swift @@ -16,6 +16,7 @@ public class Account: PostgresStORM { public var id = "" public var username = "" public var password = "" + public var salt = "" public var email = "" public var usertype: AccountType = .provisional public var source = "local" // local, facebook, etc @@ -108,23 +109,12 @@ public class Account: PostgresStORM { id = _r.secureToken } - public static func makeShadow(from: String) -> String? { - if let hashData = from.digest(.sha384) { - let hashKeyData:[UInt8] = hashData[0..<32].map {$0} - let ivData:[UInt8] = hashData[32..<48].map {$0} - let data:[UInt8] = from.utf8.map { $0 } - if let x = data.encrypt(.aes_128_cbc, key: hashKeyData, iv: ivData), - let y = x.encode(.base64), - let z = String(validatingUTF8: y) { - return z - } - } - return nil - } - public func makePassword(_ p1: String) { - if let shadow = Account.makeShadow(from: p1) { + if let random = ([UInt8](randomCount: 16)).encode(.hex), + let salt = String(validatingUTF8: random), + let shadow = p1.encrypt(.aes_128_cbc, password: p1, salt: salt) { password = shadow + self.salt = salt } } @@ -200,22 +190,19 @@ public class Account: PostgresStORM { // Register User public static func login(_ u: String, _ p: String) throws -> Account { - if let shadow = Account.makeShadow(from: p) { - let acc = Account() - let criteria = ["username":u,"password":shadow] - do { - try acc.find(criteria) - if acc.usertype == .provisional { - throw OAuth2ServerError.loginError - } - return acc - } catch { - print(error) - throw OAuth2ServerError.loginError - } - } else { - throw OAuth2ServerError.loginError - } + let acc = Account() + let criteria = ["username":u] + do { + try acc.find(criteria) + guard let pwd = acc.password.decrypt(.aes_128_cbc, password: p, salt: acc.salt), + pwd == p, acc.usertype != .provisional else { + throw OAuth2ServerError.loginError + } + return acc + } catch { + print(error) + throw OAuth2ServerError.loginError + } } public static func listUsers() -> [[String: Any]] {