@capgo/capacitor-updater 8.0.1 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CapgoCapacitorUpdater.podspec +7 -5
  2. package/Package.swift +9 -7
  3. package/README.md +984 -215
  4. package/android/build.gradle +24 -12
  5. package/android/proguard-rules.pro +22 -5
  6. package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +110 -22
  7. package/android/src/main/java/ee/forgr/capacitor_updater/Callback.java +2 -2
  8. package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +1316 -489
  9. package/android/src/main/java/ee/forgr/capacitor_updater/{CapacitorUpdater.java → CapgoUpdater.java} +662 -203
  10. package/android/src/main/java/ee/forgr/capacitor_updater/{CryptoCipherV2.java → CryptoCipher.java} +138 -33
  11. package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +0 -3
  12. package/android/src/main/java/ee/forgr/capacitor_updater/DelayUpdateUtils.java +260 -0
  13. package/android/src/main/java/ee/forgr/capacitor_updater/DeviceIdHelper.java +221 -0
  14. package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +497 -133
  15. package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +80 -25
  16. package/android/src/main/java/ee/forgr/capacitor_updater/Logger.java +338 -0
  17. package/android/src/main/java/ee/forgr/capacitor_updater/ShakeDetector.java +72 -0
  18. package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +169 -0
  19. package/dist/docs.json +873 -154
  20. package/dist/esm/definitions.d.ts +881 -114
  21. package/dist/esm/definitions.js.map +1 -1
  22. package/dist/esm/history.d.ts +1 -0
  23. package/dist/esm/history.js +283 -0
  24. package/dist/esm/history.js.map +1 -0
  25. package/dist/esm/index.d.ts +1 -0
  26. package/dist/esm/index.js +1 -0
  27. package/dist/esm/index.js.map +1 -1
  28. package/dist/esm/web.d.ts +12 -1
  29. package/dist/esm/web.js +29 -2
  30. package/dist/esm/web.js.map +1 -1
  31. package/dist/plugin.cjs.js +311 -2
  32. package/dist/plugin.cjs.js.map +1 -1
  33. package/dist/plugin.js +311 -2
  34. package/dist/plugin.js.map +1 -1
  35. package/ios/Sources/CapacitorUpdaterPlugin/AES.swift +69 -0
  36. package/ios/Sources/CapacitorUpdaterPlugin/BigInt.swift +55 -0
  37. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/BundleInfo.swift +37 -10
  38. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/BundleStatus.swift +1 -1
  39. package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +1610 -0
  40. package/ios/{Plugin/CapacitorUpdater.swift → Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift} +541 -231
  41. package/ios/Sources/CapacitorUpdaterPlugin/CryptoCipher.swift +286 -0
  42. package/ios/Sources/CapacitorUpdaterPlugin/DelayUpdateUtils.swift +220 -0
  43. package/ios/Sources/CapacitorUpdaterPlugin/DeviceIdHelper.swift +120 -0
  44. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/InternalUtils.swift +54 -0
  45. package/ios/Sources/CapacitorUpdaterPlugin/Logger.swift +310 -0
  46. package/ios/Sources/CapacitorUpdaterPlugin/RSA.swift +274 -0
  47. package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +112 -0
  48. package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/UserDefaultsExtension.swift +0 -2
  49. package/package.json +21 -19
  50. package/ios/Plugin/CapacitorUpdaterPlugin.swift +0 -975
  51. package/ios/Plugin/CryptoCipherV2.swift +0 -310
  52. /package/{LICENCE → LICENSE} +0 -0
  53. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/DelayCondition.swift +0 -0
  54. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/DelayUntilNext.swift +0 -0
  55. /package/ios/{Plugin → Sources/CapacitorUpdaterPlugin}/Info.plist +0 -0
@@ -1,310 +0,0 @@
1
- /*
2
- * This Source Code Form is subject to the terms of the Mozilla Public
3
- * License, v. 2.0. If a copy of the MPL was not distributed with this
4
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
- */
6
-
7
- import Foundation
8
- import CommonCrypto
9
- import CryptoKit
10
-
11
- ///
12
- /// Constants
13
- ///
14
- private enum CryptoCipherConstants {
15
- static let rsaKeySizeInBits: NSNumber = 2048
16
- static let aesAlgorithm: CCAlgorithm = CCAlgorithm(kCCAlgorithmAES)
17
- static let aesOptions: CCOptions = CCOptions(kCCOptionPKCS7Padding)
18
- static let rsaAlgorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA256
19
- }
20
- ///
21
- /// The AES key. Contains both the initialization vector and secret key.
22
- ///
23
- public struct AES128Key {
24
- /// Initialization vector
25
- private let iv: Data
26
- private let aes128Key: Data
27
- #if DEBUG
28
- public var __debug_iv: Data { iv }
29
- public var __debug_aes128Key: Data { aes128Key }
30
- #endif
31
- init(iv: Data, aes128Key: Data) {
32
- self.iv = iv
33
- self.aes128Key = aes128Key
34
- }
35
- ///
36
- /// Takes the data and uses the private key to decrypt it. Will call `CCCrypt` in CommonCrypto
37
- /// and provide it `ivData` for the initialization vector. Will use cipher block chaining (CBC) as
38
- /// the mode of operation.
39
- ///
40
- /// Returns the decrypted data.
41
- ///
42
- public func decrypt(data: Data) -> Data? {
43
- let encryptedData: UnsafePointer<UInt8> = (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count)
44
- let encryptedDataLength: Int = data.count
45
-
46
- if let result: NSMutableData = NSMutableData(length: encryptedDataLength) {
47
- let keyData: UnsafePointer<UInt8> = (self.aes128Key as NSData).bytes.bindMemory(to: UInt8.self, capacity: self.aes128Key.count)
48
- let keyLength: size_t = size_t(self.aes128Key.count)
49
- let ivData: UnsafePointer<UInt8> = (iv as NSData).bytes.bindMemory(to: UInt8.self, capacity: self.iv.count)
50
-
51
- let decryptedData: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>(result.mutableBytes.assumingMemoryBound(to: UInt8.self))
52
- let decryptedDataLength: size_t = size_t(result.length)
53
-
54
- var decryptedLength: size_t = 0
55
-
56
- let status: CCCryptorStatus = CCCrypt(CCOperation(kCCDecrypt), CryptoCipherConstants.aesAlgorithm, CryptoCipherConstants.aesOptions, keyData, keyLength, ivData, encryptedData, encryptedDataLength, decryptedData, decryptedDataLength, &decryptedLength)
57
-
58
- if Int32(status) == Int32(kCCSuccess) {
59
- result.length = Int(decryptedLength)
60
- return result as Data
61
- } else {
62
- return nil
63
- }
64
- } else {
65
- return nil
66
- }
67
- }
68
- }
69
-
70
- ///
71
- /// The RSA public key.
72
- ///
73
- public struct RSAPublicKey {
74
- private let publicKey: SecKey
75
-
76
- #if DEBUG
77
- public var __debug_publicKey: SecKey { self.publicKey }
78
- #endif
79
-
80
- fileprivate init(publicKey: SecKey) {
81
- self.publicKey = publicKey
82
- }
83
-
84
- ///
85
- /// Takes the data and uses the public key to decrypt it.
86
- /// Returns the decrypted data.
87
- ///
88
- public func decrypt(data: Data) -> Data? {
89
- do {
90
- guard let decryptedData = RSAPublicKey.decryptWithRSAKey(data, rsaKeyRef: self.publicKey, padding: SecPadding()) else {
91
- throw CustomError.cannotDecryptSessionKey
92
- }
93
-
94
- return decryptedData
95
- } catch {
96
- print("Error decrypting data: \(error)")
97
- return nil
98
- }
99
- }
100
-
101
- ///
102
- /// Allows you to load an RSA public key (i.e. one downloaded from the net).
103
- ///
104
- public static func load(rsaPublicKey: String) -> RSAPublicKey? {
105
- var pubKey: String = rsaPublicKey
106
- pubKey = pubKey.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
107
- pubKey = pubKey.replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: "")
108
- pubKey = pubKey.replacingOccurrences(of: "\\n+", with: "", options: .regularExpression)
109
- pubKey = pubKey.trimmingCharacters(in: .whitespacesAndNewlines)
110
- do {
111
- guard let rsaPublicKeyData: Data = Data(base64Encoded: String(pubKey)) else {
112
- throw CustomError.cannotDecode
113
- }
114
-
115
- guard let publicKey: SecKey = .loadPublicFromData(rsaPublicKeyData) else {
116
- throw CustomError.cannotDecode
117
- }
118
-
119
- return RSAPublicKey(publicKey: publicKey)
120
- } catch {
121
- print("Error load RSA: \(error)")
122
- return nil
123
- }
124
- }
125
-
126
- // code is copied from here: https://github.com/btnguyen2k/swiftutils/blob/88494f4c635b6c6d42ef0fb30a7d666acd38c4fa/SwiftUtils/RSAUtils.swift#L393
127
- public static func decryptWithRSAKey(_ encryptedData: Data, rsaKeyRef: SecKey, padding: SecPadding) -> Data? {
128
- let blockSize = SecKeyGetBlockSize(rsaKeyRef)
129
- let dataSize = encryptedData.count / MemoryLayout<UInt8>.size
130
-
131
- var encryptedDataAsArray = [UInt8](repeating: 0, count: dataSize)
132
- (encryptedData as NSData).getBytes(&encryptedDataAsArray, length: dataSize)
133
-
134
- var decryptedData = [UInt8](repeating: 0, count: 0)
135
- var idx = 0
136
- while idx < encryptedDataAsArray.count {
137
- var idxEnd = idx + blockSize
138
- if idxEnd > encryptedDataAsArray.count {
139
- idxEnd = encryptedDataAsArray.count
140
- }
141
- var chunkData = [UInt8](repeating: 0, count: blockSize)
142
- for i in idx..<idxEnd {
143
- chunkData[i-idx] = encryptedDataAsArray[i]
144
- }
145
-
146
- var decryptedDataBuffer = [UInt8](repeating: 0, count: blockSize)
147
- var decryptedDataLength = blockSize
148
-
149
- let status = SecKeyDecrypt(rsaKeyRef, padding, chunkData, idxEnd-idx, &decryptedDataBuffer, &decryptedDataLength)
150
- if status != noErr {
151
- return nil
152
- }
153
- let finalData = removePadding(decryptedDataBuffer)
154
- decryptedData += finalData
155
-
156
- idx += blockSize
157
- }
158
-
159
- return Data(decryptedData)
160
- }
161
-
162
- // code is copied from here: https://github.com/btnguyen2k/swiftutils/blob/88494f4c635b6c6d42ef0fb30a7d666acd38c4fa/SwiftUtils/RSAUtils.swift#L429
163
- private static func removePadding(_ data: [UInt8]) -> [UInt8] {
164
- var idxFirstZero = -1
165
- var idxNextZero = data.count
166
- for i in 0..<data.count {
167
- if data[i] == 0 {
168
- if idxFirstZero < 0 {
169
- idxFirstZero = i
170
- } else {
171
- idxNextZero = i
172
- break
173
- }
174
- }
175
- }
176
- if idxNextZero-idxFirstZero-1 == 0 {
177
- idxNextZero = idxFirstZero
178
- idxFirstZero = -1
179
- }
180
- var newData = [UInt8](repeating: 0, count: idxNextZero-idxFirstZero-1)
181
- for i in idxFirstZero+1..<idxNextZero {
182
- newData[i-idxFirstZero-1] = data[i]
183
- }
184
- return newData
185
- }
186
- }
187
-
188
- fileprivate extension SecKey {
189
- func exportToData() -> Data? {
190
- var error: Unmanaged<CFError>?
191
- if let cfData: CFData = SecKeyCopyExternalRepresentation(self, &error) {
192
- if error != nil {
193
- return nil
194
- } else {
195
- return cfData as Data
196
- }
197
- } else {
198
- return nil
199
- }
200
- }
201
- static func loadPublicFromData(_ data: Data) -> SecKey? {
202
- let keyDict: [NSObject: NSObject] = [
203
- kSecAttrKeyType: kSecAttrKeyTypeRSA,
204
- kSecAttrKeyClass: kSecAttrKeyClassPublic,
205
- kSecAttrKeySizeInBits: CryptoCipherConstants.rsaKeySizeInBits
206
- ]
207
- return SecKeyCreateWithData(data as NSData, keyDict as CFDictionary, nil)
208
- }
209
- static func loadPrivateFromData(_ data: Data) -> SecKey? {
210
- let keyDict: [NSObject: NSObject] = [
211
- kSecAttrKeyType: kSecAttrKeyTypeRSA,
212
- kSecAttrKeyClass: kSecAttrKeyClassPrivate,
213
- kSecAttrKeySizeInBits: CryptoCipherConstants.rsaKeySizeInBits
214
- ]
215
- return SecKeyCreateWithData(data as CFData, keyDict as CFDictionary, nil)
216
- }
217
- }
218
-
219
- public struct CryptoCipherV2 {
220
-
221
- public static func decryptChecksum(checksum: String, publicKey: String, version: String) throws -> String {
222
- if publicKey.isEmpty {
223
- return checksum
224
- }
225
- do {
226
- let checksumBytes: Data = Data(base64Encoded: checksum)!
227
- guard let rsaPublicKey: RSAPublicKey = .load(rsaPublicKey: publicKey) else {
228
- print("cannot decode publicKey", publicKey)
229
- throw CustomError.cannotDecode
230
- }
231
- guard let decryptedChecksum = rsaPublicKey.decrypt(data: checksumBytes) else {
232
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
233
- }
234
- return decryptedChecksum.base64EncodedString()
235
- } catch {
236
- print("\(CapacitorUpdater.TAG) Cannot decrypt checksum: \(checksum)", error)
237
- throw CustomError.cannotDecode
238
- }
239
- }
240
- public static func calcChecksum(filePath: URL) -> String {
241
- let bufferSize = 1024 * 1024 * 5 // 5 MB
242
- var sha256 = SHA256()
243
-
244
- do {
245
- let fileHandle = try FileHandle(forReadingFrom: filePath)
246
- defer {
247
- fileHandle.closeFile()
248
- }
249
-
250
- while autoreleasepool(invoking: {
251
- let fileData = fileHandle.readData(ofLength: bufferSize)
252
- if fileData.count > 0 {
253
- sha256.update(data: fileData)
254
- return true // Continue
255
- } else {
256
- return false // End of file
257
- }
258
- }) {}
259
-
260
- let digest = sha256.finalize()
261
- return digest.compactMap { String(format: "%02x", $0) }.joined()
262
- } catch {
263
- print("\(CapacitorUpdater.TAG) Cannot get checksum: \(filePath.path)", error)
264
- return ""
265
- }
266
- }
267
-
268
- public static func decryptFile(filePath: URL, publicKey: String, sessionKey: String, version: String) throws {
269
- if publicKey.isEmpty || sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
270
- print("\(CapacitorUpdater.TAG) Cannot find public key or sessionKey")
271
- return
272
- }
273
- do {
274
- guard let rsaPublicKey: RSAPublicKey = .load(rsaPublicKey: publicKey) else {
275
- print("cannot decode publicKey", publicKey)
276
- throw CustomError.cannotDecode
277
- }
278
-
279
- let sessionKeyArray: [String] = sessionKey.components(separatedBy: ":")
280
- guard let ivData: Data = Data(base64Encoded: sessionKeyArray[0]) else {
281
- print("cannot decode sessionKey", sessionKey)
282
- throw CustomError.cannotDecode
283
- }
284
-
285
- guard let sessionKeyDataEncrypted = Data(base64Encoded: sessionKeyArray[1]) else {
286
- throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
287
- }
288
-
289
- guard let sessionKeyDataDecrypted = rsaPublicKey.decrypt(data: sessionKeyDataEncrypted) else {
290
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
291
- }
292
-
293
- let aesPrivateKey = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted)
294
-
295
- guard let encryptedData = try? Data(contentsOf: filePath) else {
296
- throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
297
- }
298
-
299
- guard let decryptedData = aesPrivateKey.decrypt(data: encryptedData) else {
300
- throw NSError(domain: "Failed to decrypt data", code: 4, userInfo: nil)
301
- }
302
-
303
- try decryptedData.write(to: filePath)
304
-
305
- } catch {
306
- print("\(CapacitorUpdater.TAG) Cannot decode: \(filePath.path)", error)
307
- throw CustomError.cannotDecode
308
- }
309
- }
310
- }
File without changes