Skip to content

Commit f1ac186

Browse files
committed
🛠 refactoring, generics, remove redudant class etc
1 parent d40a79c commit f1ac186

File tree

8 files changed

+149
-138
lines changed

8 files changed

+149
-138
lines changed

Example/web3swiftBrowser/web3swiftBrowser/PrefferedModels.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,33 @@ struct Wallet {
2020
var password = "web3swift" // We recommend here and everywhere to use the password set by the user.
2121

2222
var address: String
23-
var keystore: AbstractKeystore
23+
2424
var data: Data
2525
var isHD: Bool
2626

2727
init(type: walletType) {
2828
switch type {
2929
case .EthereumKeystoreV3:
30-
keystore = try! EthereumKeystoreV3(password: password)!
30+
let keystore = try! EthereumKeystoreV3(password: password)!
3131
self.address = keystore.addresses!.first!.address
32-
self.data = try! JSONEncoder().encode(keystore.giveKeystoreParams())
32+
self.data = try! JSONEncoder().encode(keystore.keystoreParams)
3333
self.isHD = false
34+
self.address = keystore.addresses!.first!.address
3435

3536
case .BIP39:
3637
let mnemonics = try! BIP39.generateMnemonics(bitsOfEntropy: bitsOfEntropy)!
37-
keystore = try! BIP32Keystore(
38+
let keystore = try! BIP32Keystore(
3839
mnemonics: mnemonics,
3940
password: password,
4041
mnemonicsPassword: "",
4142
language: .english)!
4243
self.name = "HD Wallet"
43-
self.data = try! JSONEncoder().encode(keystore.giveKeystoreParams())
44+
self.data = try! JSONEncoder().encode(keystore.keystoreParams)
4445
self.isHD = true
46+
self.address = keystore.addresses!.first!.address
4547
}
4648

47-
self.address = keystore.addresses!.first!.address
49+
4850
}
4951
}
5052

Sources/web3swift/HookedFunctions/Web3+BrowserFunctions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ extension web3.BrowserFunctions {
196196
transaction.chainID = self.web3.provider.network?.chainID
197197
}
198198

199-
guard let keystore: AbstractKeystore = keystoreManager.walletForAddress(from) else {return nil}
199+
guard let keystore = keystoreManager.walletForAddress(from) else {return nil}
200200
try Web3Signer.signTX(transaction: &transaction, keystore: keystore, account: from, password: password)
201201
print(transaction)
202202
let signedData = transaction.encode(forSignature: false, chainID: nil)?.toHexString().addHexPrefix()

Sources/web3swift/KeystoreManager/AbstractKeystore.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import Foundation
99
//import EthereumAddress
1010

1111
public protocol AbstractKeystore {
12-
associatedtype Params: AbstractKeystoreParams
13-
func giveKeystoreParams() -> Params
1412
var addresses: [EthereumAddress]? { get }
1513
var isHDKeystore: Bool { get }
1614
func UNSAFE_getPrivateKeyData(password: String, account: EthereumAddress) throws -> Data

Sources/web3swift/KeystoreManager/BIP32Keystore.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import Foundation
1212

1313
public class BIP32Keystore: AbstractKeystore {
1414

15-
public typealias Params = KeystoreParamsBIP32
16-
public func giveKeystoreParams() -> Params {
17-
self.keystoreParams!
18-
}
1915

2016
// Protocol
17+
public var isHDKeystore: Bool = true
18+
19+
public var keystoreParams: KeystoreParamsBIP32?
20+
public var paths: [String: EthereumAddress] = [String: EthereumAddress]()
21+
22+
public var rootPrefix: String
2123

2224
public var addresses: [EthereumAddress]? {
2325
get {
@@ -32,8 +34,6 @@ public class BIP32Keystore: AbstractKeystore {
3234
}
3335
}
3436

35-
public var isHDKeystore: Bool = true
36-
3737
public func UNSAFE_getPrivateKeyData(password: String, account: EthereumAddress) throws -> Data {
3838
if let key = self.paths.keyForValue(value: account) {
3939
guard let decryptedRootNode = try? self.getPrefixNodeData(password) else {
@@ -62,9 +62,6 @@ public class BIP32Keystore: AbstractKeystore {
6262

6363
// --------------
6464

65-
public var keystoreParams: KeystoreParamsBIP32?
66-
public var paths: [String: EthereumAddress] = [String: EthereumAddress]()
67-
public var rootPrefix: String
6865

6966
public convenience init?(_ jsonString: String) {
7067
let lowercaseJSON = jsonString.lowercased()

Sources/web3swift/KeystoreManager/EthereumKeystoreV3.swift

Lines changed: 125 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,11 @@ import CryptoSwift
99
import Foundation
1010

1111
public class EthereumKeystoreV3: AbstractKeystore {
12-
public typealias Params = KeystoreParamsV3
13-
public var keystoreParams: Params?
14-
15-
public func giveKeystoreParams() -> Params {
16-
keystoreParams!
17-
}
18-
19-
2012
// Protocol
21-
private var address: EthereumAddress?
2213
public var isHDKeystore: Bool = false
14+
private var address: EthereumAddress?
15+
public var keystoreParams: KeystoreParamsV3?
16+
2317

2418
public var addresses: [EthereumAddress]? {
2519
get {
@@ -32,7 +26,9 @@ public class EthereumKeystoreV3: AbstractKeystore {
3226

3327
public func UNSAFE_getPrivateKeyData(password: String, account: EthereumAddress) throws -> Data {
3428
if self.addresses?.count == 1 && account == self.addresses?.last {
35-
guard let privateKey = try? self.getKeyData(password) else {throw AbstractKeystoreError.invalidPasswordError}
29+
guard let privateKey = try? self.getKeyData(password) else {
30+
throw AbstractKeystoreError.invalidPasswordError
31+
}
3632
return privateKey
3733
}
3834
throw AbstractKeystoreError.invalidAccountError
@@ -48,18 +44,26 @@ public class EthereumKeystoreV3: AbstractKeystore {
4844

4945
public convenience init?(_ jsonString: String) {
5046
let lowercaseJSON = jsonString.lowercased()
51-
guard let jsonData = lowercaseJSON.data(using: .utf8) else {return nil}
47+
guard let jsonData = lowercaseJSON.data(using: .utf8) else {
48+
return nil
49+
}
5250
self.init(jsonData)
5351
}
5452

5553
public convenience init?(_ jsonData: Data) {
56-
guard let keystoreParams = try? JSONDecoder().decode(KeystoreParamsV3.self, from: jsonData) else {return nil}
54+
guard let keystoreParams = try? JSONDecoder().decode(KeystoreParamsV3.self, from: jsonData) else {
55+
return nil
56+
}
5757
self.init(keystoreParams)
5858
}
5959

6060
public init?(_ keystoreParams: KeystoreParamsV3) {
61-
if (keystoreParams.version != 3) {return nil}
62-
if (keystoreParams.crypto.version != nil && keystoreParams.crypto.version != "1") {return nil}
61+
if (keystoreParams.version != 3) {
62+
return nil
63+
}
64+
if (keystoreParams.crypto.version != nil && keystoreParams.crypto.version != "1") {
65+
return nil
66+
}
6367
self.keystoreParams = keystoreParams
6468
if keystoreParams.address != nil {
6569
self.address = EthereumAddress(keystoreParams.address!.addHexPrefix())
@@ -68,29 +72,43 @@ public class EthereumKeystoreV3: AbstractKeystore {
6872
}
6973
}
7074

71-
public init? (password: String = "web3swift", aesMode: String = "aes-128-cbc") throws {
72-
guard var newPrivateKey = SECP256K1.generatePrivateKey() else {return nil}
73-
defer {Data.zero(&newPrivateKey)}
75+
public init?(password: String = "web3swift", aesMode: String = "aes-128-cbc") throws {
76+
guard var newPrivateKey = SECP256K1.generatePrivateKey() else {
77+
return nil
78+
}
79+
defer {
80+
Data.zero(&newPrivateKey)
81+
}
7482
try encryptDataToStorage(password, keyData: newPrivateKey, aesMode: aesMode)
7583
}
7684

77-
public init? (privateKey: Data, password: String = "web3swift", aesMode: String = "aes-128-cbc") throws {
78-
guard privateKey.count == 32 else {return nil}
79-
guard SECP256K1.verifyPrivateKey(privateKey: privateKey) else {return nil}
85+
public init?(privateKey: Data, password: String = "web3swift", aesMode: String = "aes-128-cbc") throws {
86+
guard privateKey.count == 32 else {
87+
return nil
88+
}
89+
guard SECP256K1.verifyPrivateKey(privateKey: privateKey) else {
90+
return nil
91+
}
8092
try encryptDataToStorage(password, keyData: privateKey, aesMode: aesMode)
8193
}
8294

83-
fileprivate func encryptDataToStorage(_ password: String, keyData: Data?, dkLen: Int=32, N: Int = 4096, R: Int = 6, P: Int = 1, aesMode: String = "aes-128-cbc") throws {
95+
fileprivate func encryptDataToStorage(_ password: String, keyData: Data?, dkLen: Int = 32, N: Int = 4096, R: Int = 6, P: Int = 1, aesMode: String = "aes-128-cbc") throws {
8496
if (keyData == nil) {
8597
throw AbstractKeystoreError.encryptionError("Encryption without key data")
8698
}
8799
let saltLen = 32;
88-
guard let saltData = Data.randomBytes(length: saltLen) else {throw AbstractKeystoreError.noEntropyError}
89-
guard let derivedKey = scrypt(password: password, salt: saltData, length: dkLen, N: N, R: R, P: P) else {throw AbstractKeystoreError.keyDerivationError}
90-
let last16bytes = Data(derivedKey[(derivedKey.count - 16)...(derivedKey.count-1)])
100+
guard let saltData = Data.randomBytes(length: saltLen) else {
101+
throw AbstractKeystoreError.noEntropyError
102+
}
103+
guard let derivedKey = scrypt(password: password, salt: saltData, length: dkLen, N: N, R: R, P: P) else {
104+
throw AbstractKeystoreError.keyDerivationError
105+
}
106+
let last16bytes = Data(derivedKey[(derivedKey.count - 16)...(derivedKey.count - 1)])
91107
let encryptionKey = Data(derivedKey[0...15])
92-
guard let IV = Data.randomBytes(length: 16) else {throw AbstractKeystoreError.noEntropyError}
93-
var aesCipher : AES?
108+
guard let IV = Data.randomBytes(length: 16) else {
109+
throw AbstractKeystoreError.noEntropyError
110+
}
111+
var aesCipher: AES?
94112
switch aesMode {
95113
case "aes-128-cbc":
96114
aesCipher = try? AES(key: encryptionKey.bytes, blockMode: CBC(iv: IV.bytes), padding: .noPadding)
@@ -102,7 +120,9 @@ public class EthereumKeystoreV3: AbstractKeystore {
102120
if aesCipher == nil {
103121
throw AbstractKeystoreError.aesError
104122
}
105-
guard let encryptedKey = try aesCipher?.encrypt(keyData!.bytes) else {throw AbstractKeystoreError.aesError}
123+
guard let encryptedKey = try aesCipher?.encrypt(keyData!.bytes) else {
124+
throw AbstractKeystoreError.aesError
125+
}
106126
// let encryptedKeyData = Data(bytes:encryptedKey)
107127
let encryptedKeyData = Data(encryptedKey)
108128
var dataForMAC = Data()
@@ -112,85 +132,129 @@ public class EthereumKeystoreV3: AbstractKeystore {
112132
let kdfparams = KdfParamsV3(salt: saltData.toHexString(), dklen: dkLen, n: N, p: P, r: R, c: nil, prf: nil)
113133
let cipherparams = CipherParamsV3(iv: IV.toHexString())
114134
let crypto = CryptoParamsV3(ciphertext: encryptedKeyData.toHexString(), cipher: aesMode, cipherparams: cipherparams, kdf: "scrypt", kdfparams: kdfparams, mac: mac.toHexString(), version: nil)
115-
guard let pubKey = Web3.Utils.privateToPublic(keyData!) else {throw AbstractKeystoreError.keyDerivationError}
116-
guard let addr = Web3.Utils.publicToAddress(pubKey) else {throw AbstractKeystoreError.keyDerivationError}
135+
guard let pubKey = Web3.Utils.privateToPublic(keyData!) else {
136+
throw AbstractKeystoreError.keyDerivationError
137+
}
138+
guard let addr = Web3.Utils.publicToAddress(pubKey) else {
139+
throw AbstractKeystoreError.keyDerivationError
140+
}
117141
self.address = addr
118142
let keystoreparams = KeystoreParamsV3(address: addr.address.lowercased(), crypto: crypto, id: UUID().uuidString.lowercased(), version: 3)
119143
self.keystoreParams = keystoreparams
120144
}
121145

122-
public func regenerate(oldPassword: String, newPassword: String, dkLen: Int=32, N: Int = 4096, R: Int = 6, P: Int = 1) throws {
146+
public func regenerate(oldPassword: String, newPassword: String, dkLen: Int = 32, N: Int = 4096, R: Int = 6, P: Int = 1) throws {
123147
var keyData = try self.getKeyData(oldPassword)
124148
if keyData == nil {
125149
throw AbstractKeystoreError.encryptionError("Failed to decrypt a keystore")
126150
}
127-
defer {Data.zero(&keyData!)}
151+
defer {
152+
Data.zero(&keyData!)
153+
}
128154
try self.encryptDataToStorage(newPassword, keyData: keyData!, aesMode: self.keystoreParams!.crypto.cipher)
129155
}
130156

131157
fileprivate func getKeyData(_ password: String) throws -> Data? {
132-
guard let keystoreParams = self.keystoreParams else {return nil}
133-
guard let saltData = Data.fromHex(keystoreParams.crypto.kdfparams.salt) else {return nil}
158+
guard let keystoreParams = self.keystoreParams else {
159+
return nil
160+
}
161+
guard let saltData = Data.fromHex(keystoreParams.crypto.kdfparams.salt) else {
162+
return nil
163+
}
134164
let derivedLen = keystoreParams.crypto.kdfparams.dklen
135-
var passwordDerivedKey:Data?
165+
var passwordDerivedKey: Data?
136166
switch keystoreParams.crypto.kdf {
137167
case "scrypt":
138-
guard let N = keystoreParams.crypto.kdfparams.n else {return nil}
139-
guard let P = keystoreParams.crypto.kdfparams.p else {return nil}
140-
guard let R = keystoreParams.crypto.kdfparams.r else {return nil}
168+
guard let N = keystoreParams.crypto.kdfparams.n else {
169+
return nil
170+
}
171+
guard let P = keystoreParams.crypto.kdfparams.p else {
172+
return nil
173+
}
174+
guard let R = keystoreParams.crypto.kdfparams.r else {
175+
return nil
176+
}
141177
passwordDerivedKey = scrypt(password: password, salt: saltData, length: derivedLen, N: N, R: R, P: P)
142178
case "pbkdf2":
143-
guard let algo = keystoreParams.crypto.kdfparams.prf else {return nil}
144-
var hashVariant:HMAC.Variant?;
179+
guard let algo = keystoreParams.crypto.kdfparams.prf else {
180+
return nil
181+
}
182+
var hashVariant: HMAC.Variant?;
145183
switch algo {
146-
case "hmac-sha256" :
147-
hashVariant = HMAC.Variant.sha256
148-
case "hmac-sha384" :
149-
hashVariant = HMAC.Variant.sha384
150-
case "hmac-sha512" :
151-
hashVariant = HMAC.Variant.sha512
152-
default:
153-
hashVariant = nil
184+
case "hmac-sha256":
185+
hashVariant = HMAC.Variant.sha256
186+
case "hmac-sha384":
187+
hashVariant = HMAC.Variant.sha384
188+
case "hmac-sha512":
189+
hashVariant = HMAC.Variant.sha512
190+
default:
191+
hashVariant = nil
192+
}
193+
guard hashVariant != nil else {
194+
return nil
195+
}
196+
guard let c = keystoreParams.crypto.kdfparams.c else {
197+
return nil
198+
}
199+
guard let passData = password.data(using: .utf8) else {
200+
return nil
201+
}
202+
guard let derivedArray = try? PKCS5.PBKDF2(password: passData.bytes, salt: saltData.bytes, iterations: c, keyLength: derivedLen, variant: hashVariant!).calculate() else {
203+
return nil
154204
}
155-
guard hashVariant != nil else {return nil}
156-
guard let c = keystoreParams.crypto.kdfparams.c else {return nil}
157-
guard let passData = password.data(using: .utf8) else {return nil}
158-
guard let derivedArray = try? PKCS5.PBKDF2(password: passData.bytes, salt: saltData.bytes, iterations: c, keyLength: derivedLen, variant: hashVariant!).calculate() else {return nil}
159205
// passwordDerivedKey = Data(bytes:derivedArray)
160206
passwordDerivedKey = Data(derivedArray)
161207
default:
162208
return nil
163209
}
164-
guard let derivedKey = passwordDerivedKey else {return nil}
210+
guard let derivedKey = passwordDerivedKey else {
211+
return nil
212+
}
165213
var dataForMAC = Data()
166214
let derivedKeyLast16bytes = Data(derivedKey[(derivedKey.count - 16)...(derivedKey.count - 1)])
167215
dataForMAC.append(derivedKeyLast16bytes)
168-
guard let cipherText = Data.fromHex(keystoreParams.crypto.ciphertext) else {return nil}
169-
if (cipherText.count != 32) {return nil}
216+
guard let cipherText = Data.fromHex(keystoreParams.crypto.ciphertext) else {
217+
return nil
218+
}
219+
if (cipherText.count != 32) {
220+
return nil
221+
}
170222
dataForMAC.append(cipherText)
171223
let mac = dataForMAC.sha3(.keccak256)
172-
guard let calculatedMac = Data.fromHex(keystoreParams.crypto.mac), mac.constantTimeComparisonTo(calculatedMac) else {return nil}
224+
guard let calculatedMac = Data.fromHex(keystoreParams.crypto.mac), mac.constantTimeComparisonTo(calculatedMac) else {
225+
return nil
226+
}
173227
let cipher = keystoreParams.crypto.cipher
174228
let decryptionKey = derivedKey[0...15]
175-
guard let IV = Data.fromHex(keystoreParams.crypto.cipherparams.iv) else {return nil}
176-
var decryptedPK:Array<UInt8>?
229+
guard let IV = Data.fromHex(keystoreParams.crypto.cipherparams.iv) else {
230+
return nil
231+
}
232+
var decryptedPK: Array<UInt8>?
177233
switch cipher {
178234
case "aes-128-ctr":
179-
guard let aesCipher = try? AES(key: decryptionKey.bytes, blockMode: CTR(iv: IV.bytes), padding: .noPadding) else {return nil}
235+
guard let aesCipher = try? AES(key: decryptionKey.bytes, blockMode: CTR(iv: IV.bytes), padding: .noPadding) else {
236+
return nil
237+
}
180238
decryptedPK = try aesCipher.decrypt(cipherText.bytes)
181239
case "aes-128-cbc":
182-
guard let aesCipher = try? AES(key: decryptionKey.bytes, blockMode: CBC(iv: IV.bytes), padding: .noPadding) else {return nil}
240+
guard let aesCipher = try? AES(key: decryptionKey.bytes, blockMode: CBC(iv: IV.bytes), padding: .noPadding) else {
241+
return nil
242+
}
183243
decryptedPK = try? aesCipher.decrypt(cipherText.bytes)
184244
default:
185245
return nil
186246
}
187-
guard decryptedPK != nil else {return nil}
247+
guard decryptedPK != nil else {
248+
return nil
249+
}
188250
// return Data(bytes:decryptedPK!)
189251
return Data(decryptedPK!)
190252
}
191253

192254
public func serialize() throws -> Data? {
193-
guard let params = self.keystoreParams else {return nil}
255+
guard let params = self.keystoreParams else {
256+
return nil
257+
}
194258
let data = try JSONEncoder().encode(params)
195259
return data
196260
}

0 commit comments

Comments
 (0)