Skip to content

Commit

Permalink
Fix backup crypto scrypt.
Browse files Browse the repository at this point in the history
- call unlock module for backup files
  • Loading branch information
ant013 committed Oct 20, 2023
1 parent e99e7c6 commit 2c361db
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,7 @@
ABC9A20D2DDF8736293DE5C5 /* CoinIndicatorViewItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A76776AD840DBFAA1804 /* CoinIndicatorViewItemFactory.swift */; };
ABC9A20F6F7D5EA2A1A55A9E /* ContactLabelService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB89F64056FFB98928E7 /* ContactLabelService.swift */; };
ABC9A227648FF076E9518703 /* ContactBookHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AE12A5E8B9FB24FFE42F /* ContactBookHelper.swift */; };
ABC9A23C735BD2271B6A262A /* RestoreManagerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A999428368A8FA264CA4 /* RestoreManagerViewModel.swift */; };
ABC9A2462F3F928644435B86 /* NftAssetModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AD35D41AEEBD38AA08B5 /* NftAssetModule.swift */; };
ABC9A251119A2486465B315E /* WalletConnectService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A1136889E6976E17B347 /* WalletConnectService.swift */; };
ABC9A2542EA47C2ED85C06B9 /* WalletConnectListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AE5FD79ECC4AC85B86FA /* WalletConnectListViewController.swift */; };
Expand Down Expand Up @@ -2279,6 +2280,7 @@
ABC9AA462C94586CD8233295 /* WalletConnectAppShowModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A9E2C039C005650491D2 /* WalletConnectAppShowModule.swift */; };
ABC9AA4B0A6C33CAD5F3B050 /* ChartIndicatorsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB3EC7A1FB0D6C9F7F89 /* ChartIndicatorsModule.swift */; };
ABC9AA78419B8BFEC23E8E02 /* TokenSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A791A47F4F1E71B51B3B /* TokenSelectView.swift */; };
ABC9AA802C533F489EB72FDE /* RestoreManagerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A999428368A8FA264CA4 /* RestoreManagerViewModel.swift */; };
ABC9AA80C5197F9CC6221FC8 /* WalletBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AECEEB35D57CB0965E79 /* WalletBackup.swift */; };
ABC9AA85AC9DC60A08211D16 /* SendZcashViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A8B3C65C9F0285483160 /* SendZcashViewController.swift */; };
ABC9AA86292CD59848A130F9 /* MacdIndicatorDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AA8F31619609907AD67E /* MacdIndicatorDataSource.swift */; };
Expand Down Expand Up @@ -3933,6 +3935,7 @@
ABC9A950663B76424B1761B3 /* EventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventHandler.swift; sourceTree = "<group>"; };
ABC9A9628A708749A31EEA70 /* ProFeaturesAuthorizationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProFeaturesAuthorizationManager.swift; sourceTree = "<group>"; };
ABC9A99184EE1D5D052C52E9 /* ContactBookSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactBookSettingsViewController.swift; sourceTree = "<group>"; };
ABC9A999428368A8FA264CA4 /* RestoreManagerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreManagerViewModel.swift; sourceTree = "<group>"; };
ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullCoin.swift; sourceTree = "<group>"; };
ABC9A9C09ECB9B0CCBAD8C21 /* SendEip1155ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendEip1155ViewController.swift; sourceTree = "<group>"; };
ABC9A9CB516D0B925DE22C1E /* RestoreFileConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreFileConfigurationViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7551,6 +7554,7 @@
children = (
ABC9AD42C324F58B5EE00610 /* BackupManagerModule.swift */,
ABC9AEA4B072067A9F10BE36 /* BackupManagerViewController.swift */,
ABC9A999428368A8FA264CA4 /* RestoreManagerViewModel.swift */,
);
path = BackupManagerLegacy;
sourceTree = "<group>";
Expand Down Expand Up @@ -9509,6 +9513,7 @@
11B3542694E183882F9BEBEC /* CoinPageView.swift in Sources */,
11B35B5451BA0A3C825809A2 /* TabHeaderView.swift in Sources */,
11B35DDE363387B6E7A1D3B9 /* TabButtonStyle.swift in Sources */,
ABC9AA802C533F489EB72FDE /* RestoreManagerViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -10845,6 +10850,7 @@
11B3522207EA307D94070776 /* CoinPageView.swift in Sources */,
11B3550A6826CF513B1A77F0 /* TabHeaderView.swift in Sources */,
11B3551F51D987A150C3BC26 /* TabButtonStyle.swift in Sources */,
ABC9A23C735BD2271B6A262A /* RestoreManagerViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -11272,7 +11278,7 @@
repositoryURL = "https://github.com/horizontalsystems/LitecoinKit.Swift";
requirement = {
kind = exactVersion;
version = 2.0.0;
version = 2.1.0;
};
};
D3604E6E28F03AC70066C366 /* XCRemoteSwiftPackageReference "MarketKit.Swift" */ = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import LitecoinKit
import BitcoinCore
import RxSwift
import MarketKit
import Foundation
import HdWalletKit
import LitecoinKit
import MarketKit
import RxSwift

class LitecoinAdapter: BitcoinBaseAdapter {
private let litecoinKit: LitecoinKit.Kit
Expand All @@ -11,6 +12,20 @@ class LitecoinAdapter: BitcoinBaseAdapter {
let networkType: LitecoinKit.Kit.NetworkType = .mainNet
let logger = App.shared.logger.scoped(with: "LitecoinKit")

let hasher: (Data) -> Data = { data in
let params = LitecoinKit.Kit.defaultScryptParams

let result = try? BackupCryptoHelper.makeScrypt(
pass: data,
salt: data,
dkLen: params.length,
N: params.N,
r: params.r,
p: params.p
)
return result ?? Data()
}

switch wallet.account.type {
case .mnemonic:
guard let seed = wallet.account.type.mnemonicSeed else {
Expand All @@ -22,27 +37,29 @@ class LitecoinAdapter: BitcoinBaseAdapter {
}

litecoinKit = try LitecoinKit.Kit(
seed: seed,
purpose: derivation.purpose,
walletId: wallet.account.id,
syncMode: syncMode,
networkType: networkType,
confirmationsThreshold: BitcoinBaseAdapter.confirmationsThreshold,
logger: logger
seed: seed,
purpose: derivation.purpose,
walletId: wallet.account.id,
syncMode: syncMode,
hasher: hasher,
networkType: networkType,
confirmationsThreshold: BitcoinBaseAdapter.confirmationsThreshold,
logger: logger
)
case let .hdExtendedKey(key):
guard let derivation = wallet.token.type.derivation else {
throw AdapterError.wrongParameters
}

litecoinKit = try LitecoinKit.Kit(
extendedKey: key,
purpose: derivation.purpose,
walletId: wallet.account.id,
syncMode: syncMode,
networkType: networkType,
confirmationsThreshold: BitcoinBaseAdapter.confirmationsThreshold,
logger: logger
extendedKey: key,
purpose: derivation.purpose,
walletId: wallet.account.id,
syncMode: syncMode,
hasher: hasher,
networkType: networkType,
confirmationsThreshold: BitcoinBaseAdapter.confirmationsThreshold,
logger: logger
)
default:
throw AdapterError.unsupportedAccount
Expand All @@ -60,21 +77,16 @@ class LitecoinAdapter: BitcoinBaseAdapter {
override func explorerUrl(transactionHash: String) -> String? {
"https://blockchair.com/litecoin/transaction/" + transactionHash
}

}

extension LitecoinAdapter: ISendBitcoinAdapter {

var blockchainType: BlockchainType {
.litecoin
}

}

extension LitecoinAdapter {

static func clear(except excludedWalletIds: [String]) throws {
try Kit.clear(exceptFor: excludedWalletIds)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ extension BackupCrypto {
}

// validation passphrase
let isValid = (try? BackupCryptoHelper.isValid(
let isValid = try BackupCryptoHelper.isValid(
macHex: mac,
pass: passphrase,
message: cipherText.hs.data,
kdf: kdfParams
)) ?? false
)
guard isValid else {
throw RestoreCloudModule.RestoreError.invalidPassword
}
Expand Down Expand Up @@ -128,4 +128,4 @@ extension BackupCrypto {
case emptyPassphrase
case simplePassword
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation
import CommonCrypto
import ComponentKit
import CryptoSwift
import Foundation
import HsCryptoKit
import HsExtensions
import Scrypt
Expand All @@ -24,18 +26,18 @@ class BackupCryptoHelper {
key.withUnsafeBytes { key in
_ = try? iv.withUnsafeBytes { iv in
let status = CCCryptorCreateWithMode(
option,
CCMode(kCCModeCTR),
CCAlgorithm(kCCAlgorithmAES),
CCPadding(ccNoPadding),
iv.baseAddress!,
key.baseAddress!,
key.count,
nil,
0,
0,
0,
cryptorPointer
option,
CCMode(kCCModeCTR),
CCAlgorithm(kCCAlgorithmAES),
CCPadding(ccNoPadding),
iv.baseAddress!,
key.baseAddress!,
key.count,
nil,
0,
0,
0,
cryptorPointer
)
guard status == kCCSuccess else {
throw CodingError.cryptError
Expand All @@ -55,39 +57,68 @@ class BackupCryptoHelper {

return Data(resultData)
}

}

extension BackupCryptoHelper {

public static func generateInitialVector(len: Int = 16) -> Data {
Data(Array(0..<len).map { _ in UInt8.random(in: UInt8.min...UInt8.max) })
Data(Array(0 ..< len).map { _ in UInt8.random(in: UInt8.min ... UInt8.max) })
}

public static func scrypt(pass: Data, kdf: KdfParams) throws -> Data {
try Data(Scrypt.scrypt(password: pass.bytes, salt: kdf.salt.bytes, length: kdf.dklen, N: kdf.n, r: kdf.r, p: kdf.p))
public static func makeScrypt(pass: Data, salt: Data, dkLen: Int, N: UInt64, r: UInt32, p: UInt32) throws -> Data {
let result: [UInt8]
#if DEBUG
result = try scrypt(
password: pass.bytes,
salt: salt.bytes,
length: dkLen,
N: N,
r: r,
p: p
)
#else
let scryptVar = try Scrypt(
password: pass.bytes,
salt: salt.bytes,
dkLen: dkLen,
N: Int(N),
r: Int(r),
p: Int(p)
)
result = try scryptVar.calculate()
#endif
return Data(result)
}

public static func AES128(operation: Operation, ivHex: String, pass: String, message: Data, kdf: KdfParams) throws -> Data {
do {
let key = try BackupCryptoHelper.scrypt(
pass: pass.hs.data,
kdf: kdf)
let key = try BackupCryptoHelper.makeScrypt(
pass: pass.hs.data,
salt: kdf.salt.hs.data,
dkLen: kdf.dklen,
N: kdf.n,
r: kdf.r,
p: kdf.p
)
let ivData = try ivData(hex: ivHex)

return try cryptCTR(iv: ivData, key: key, data: message, option: operation.ccValue)
} catch {
if error is ScryptError {
if error is PKCS5.PBKDF2.Error || error is ScryptError {
throw CodingError.cantCreateScryptKey(error)
}
throw error
}
}

public static func mac(pass: String, message: Data, kdf: KdfParams) throws -> Data {
let key = try BackupCryptoHelper.scrypt(
let key = try BackupCryptoHelper.makeScrypt(
pass: pass.hs.data,
kdf: kdf)
salt: kdf.salt.hs.data,
dkLen: kdf.dklen,
N: kdf.n,
r: kdf.r,
p: kdf.p
)
let startIndex = kdf.dklen / 2
let lastHalfKey = key.suffix(from: startIndex)
let data = lastHalfKey + message
Expand All @@ -99,11 +130,9 @@ extension BackupCryptoHelper {
let sha3 = try mac(pass: pass, message: message, kdf: kdf)
return macHex == sha3.hs.hex
}

}

extension BackupCryptoHelper {

enum Operation {
case encrypt
case decrypt
Expand All @@ -122,5 +151,4 @@ extension BackupCryptoHelper {
case ivDataError
case cryptError
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ extension ManageAccountViewModel {
switch unlockRequest {
case .recoveryPhrase: openRecoveryPhraseRelay.accept(service.account)
case .backup: openBackupRelay.accept(service.account)
case .backupToCloud: openCloudBackupRelay.accept(service.account)
case .backupAndDeleteCloud: openBackupAndDeleteCloudRelay.accept(service.account)
}
}
Expand Down Expand Up @@ -207,7 +208,12 @@ extension ManageAccountViewModel {
}

func onTapCloudBackup() {
openCloudBackupRelay.accept(service.account)
if service.isPasscodeSet {
unlockRequest = .backupToCloud
openUnlockRelay.accept(())
} else {
openCloudBackupRelay.accept(service.account)
}
}

func onTapBackup() {
Expand All @@ -228,6 +234,7 @@ extension ManageAccountViewModel {
enum UnlockRequest {
case recoveryPhrase
case backup
case backupToCloud
case backupAndDeleteCloud
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ struct RestoreFileHelper {
return .init(name: filename, source: .wallet(oneWallet))
}

if let oneWalletV2 = try? JSONDecoder().decode(RestoreCloudModule.RestoredBackup.self, from: data) {
return .init(name: oneWalletV2.name, source: .wallet(oneWalletV2.walletBackup))
}

if let fullBackup = try? JSONDecoder().decode(FullBackup.self, from: data) {
return .init(name: filename, source: .full(fullBackup))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UIKit

class BackupManagerModule {
static func viewController() -> UIViewController {
BackupManagerViewController()
let viewModel = BackupManagerViewModel(passcodeManager: App.shared.passcodeManager)
return BackupManagerViewController(viewModel: viewModel)
}
}
Loading

0 comments on commit 2c361db

Please sign in to comment.