Move dependency from KeychainSwift, and SamKaychain to main app, update with protocol definition #5255
parent
3d228a4dbd
commit
af6688b0e4
@ -0,0 +1,87 @@ |
|||||||
|
// |
||||||
|
// KeychainStorage.swift |
||||||
|
// AlphaWallet |
||||||
|
// |
||||||
|
// Created by Vladyslav Shepitko on 02.09.2022. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import KeychainSwift |
||||||
|
import SAMKeychain |
||||||
|
import AlphaWalletFoundation |
||||||
|
import LocalAuthentication |
||||||
|
|
||||||
|
final class KeychainStorage: SecuredStorage, SecuredPasswordStorage { |
||||||
|
private let keychain: KeychainSwift |
||||||
|
|
||||||
|
init(keyPrefix: String = Constants.keychainKeyPrefix) throws { |
||||||
|
let keychain = KeychainSwift(keyPrefix: Constants.keychainKeyPrefix) |
||||||
|
keychain.synchronizable = false |
||||||
|
|
||||||
|
self.keychain = keychain |
||||||
|
if !UIApplication.shared.isProtectedDataAvailable { |
||||||
|
throw EtherKeystoreError.protectionDisabled |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var hasUserCancelledLastAccess: Bool { |
||||||
|
return keychain.lastResultCode == errSecUserCanceled |
||||||
|
} |
||||||
|
|
||||||
|
var isDataNotFoundForLastAccess: Bool { |
||||||
|
return keychain.lastResultCode == errSecItemNotFound |
||||||
|
} |
||||||
|
|
||||||
|
func set(_ value: String, forKey key: String, withAccess access: AccessOptions?) -> Bool { |
||||||
|
return keychain.set(value, forKey: key, withAccess: access?.asKeychainOptions) |
||||||
|
} |
||||||
|
|
||||||
|
func set(_ value: Data, forKey key: String, withAccess access: AccessOptions?) -> Bool { |
||||||
|
return keychain.set(value, forKey: key, withAccess: access?.asKeychainOptions) |
||||||
|
} |
||||||
|
|
||||||
|
func get(_ key: String, prompt: String?, withContext context: LAContext?) -> String? { |
||||||
|
return keychain.get(key, prompt: prompt, withContext: context) |
||||||
|
} |
||||||
|
|
||||||
|
func getData(_ key: String, prompt: String?, withContext context: LAContext?) -> Data? { |
||||||
|
return keychain.getData(key, prompt: prompt, withContext: context) |
||||||
|
} |
||||||
|
|
||||||
|
func delete(_ key: String) -> Bool { |
||||||
|
return keychain.delete(key) |
||||||
|
} |
||||||
|
|
||||||
|
func password(forService service: String, account: String) -> String? { |
||||||
|
return SAMKeychain.password(forService: service, account: account) |
||||||
|
} |
||||||
|
|
||||||
|
func setPasword(_ pasword: String, forService service: String, account: String) { |
||||||
|
SAMKeychain.setPassword(pasword, forService: service, account: account) |
||||||
|
} |
||||||
|
|
||||||
|
func deletePasword(forService service: String, account: String) { |
||||||
|
SAMKeychain.deletePassword(forService: service, account: account) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fileprivate extension AccessOptions { |
||||||
|
var asKeychainOptions: KeychainSwiftAccessOptions { |
||||||
|
switch self { |
||||||
|
case .accessibleWhenUnlocked: |
||||||
|
return .accessibleWhenUnlocked |
||||||
|
case .accessibleWhenUnlockedThisDeviceOnly(let userPresenceRequired): |
||||||
|
return .accessibleWhenUnlockedThisDeviceOnly(userPresenceRequired: userPresenceRequired) |
||||||
|
case .accessibleAfterFirstUnlock: |
||||||
|
return .accessibleAfterFirstUnlock |
||||||
|
case .accessibleAfterFirstUnlockThisDeviceOnly: |
||||||
|
return .accessibleAfterFirstUnlockThisDeviceOnly |
||||||
|
case .accessibleAlways: |
||||||
|
return .accessibleAlways |
||||||
|
case .accessibleWhenPasscodeSetThisDeviceOnly: |
||||||
|
return .accessibleWhenPasscodeSetThisDeviceOnly |
||||||
|
case .accessibleAlwaysThisDeviceOnly: |
||||||
|
return .accessibleAlwaysThisDeviceOnly |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,9 +1,27 @@ |
|||||||
// Copyright SIX DAY LLC. All rights reserved. |
// Copyright SIX DAY LLC. All rights reserved. |
||||||
|
|
||||||
import Foundation |
import Foundation |
||||||
|
import LocalAuthentication |
||||||
|
|
||||||
class LockEnterPasscodeViewModel: LockViewModel { |
class LockEnterPasscodeViewModel: LockViewModel { |
||||||
let initialLabelText = R.string.localizable.lockEnterPasscodeViewModelInitial() |
let initialLabelText = R.string.localizable.lockEnterPasscodeViewModelInitial() |
||||||
let tryAfterOneMinute = R.string.localizable.lockEnterPasscodeViewModelTryAfterOneMinute() |
let tryAfterOneMinute = R.string.localizable.lockEnterPasscodeViewModelTryAfterOneMinute() |
||||||
let loginReason = R.string.localizable.lockEnterPasscodeViewModelTouchId() |
let loginReason = R.string.localizable.lockEnterPasscodeViewModelTouchId() |
||||||
|
|
||||||
|
private var context: LAContext! |
||||||
|
var canEvaluatePolicy: Bool { |
||||||
|
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) |
||||||
|
} |
||||||
|
|
||||||
|
func invalidateContext() { |
||||||
|
context = LAContext() |
||||||
|
} |
||||||
|
|
||||||
|
func evaluatePolicy(completion: @escaping (Bool) -> Void) { |
||||||
|
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: loginReason) { success, _ in |
||||||
|
DispatchQueue.main.async { |
||||||
|
completion(success) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue