@capgo/capacitor-updater 6.27.11 → 6.34.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.
@@ -8,24 +8,59 @@ import Foundation
8
8
  import CryptoKit
9
9
  import BigInt
10
10
 
11
- // V2 Encryption - uses publicKey (modern encryption from main branch)
12
- public struct CryptoCipherV2 {
11
+ public struct CryptoCipher {
13
12
  private static var logger: Logger!
14
13
 
15
14
  public static func setLogger(_ logger: Logger) {
16
15
  self.logger = logger
17
16
  }
18
17
 
18
+ private static func hexStringToData(_ hex: String) -> Data? {
19
+ var data = Data()
20
+ var hexIterator = hex.makeIterator()
21
+ while let c1 = hexIterator.next(), let c2 = hexIterator.next() {
22
+ guard let byte = UInt8(String([c1, c2]), radix: 16) else {
23
+ return nil
24
+ }
25
+ data.append(byte)
26
+ }
27
+ return data
28
+ }
29
+
30
+ private static func isHexString(_ str: String) -> Bool {
31
+ let hexCharacterSet = CharacterSet(charactersIn: "0123456789abcdefABCDEF")
32
+ return str.unicodeScalars.allSatisfy { hexCharacterSet.contains($0) }
33
+ }
34
+
19
35
  public static func decryptChecksum(checksum: String, publicKey: String) throws -> String {
20
36
  if publicKey.isEmpty {
21
37
  logger.info("No encryption set (public key) ignored")
22
38
  return checksum
23
39
  }
24
40
  do {
25
- guard let checksumBytes = Data(base64Encoded: checksum) else {
26
- logger.error("Cannot decode checksum as base64: \(checksum)")
27
- throw CustomError.cannotDecode
41
+ // Determine if input is hex or base64 encoded
42
+ // Hex strings only contain 0-9 and a-f, while base64 contains other characters
43
+ let checksumBytes: Data
44
+ let detectedFormat: String
45
+ if isHexString(checksum) {
46
+ // Hex encoded (new format from CLI for plugin versions >= 5.30.0, 6.30.0, 7.30.0)
47
+ guard let hexData = hexStringToData(checksum) else {
48
+ logger.error("Cannot decode checksum as hex: \(checksum)")
49
+ throw CustomError.cannotDecode
50
+ }
51
+ checksumBytes = hexData
52
+ detectedFormat = "hex"
53
+ } else {
54
+ // TODO: remove backwards compatibility
55
+ // Base64 encoded (old format for backwards compatibility)
56
+ guard let base64Data = Data(base64Encoded: checksum) else {
57
+ logger.error("Cannot decode checksum as base64: \(checksum)")
58
+ throw CustomError.cannotDecode
59
+ }
60
+ checksumBytes = base64Data
61
+ detectedFormat = "base64"
28
62
  }
63
+ logger.debug("Received encrypted checksum format: \(detectedFormat) (length: \(checksum.count) chars, \(checksumBytes.count) bytes)")
29
64
 
30
65
  if checksumBytes.isEmpty {
31
66
  logger.error("Decoded checksum is empty")
@@ -42,12 +77,56 @@ public struct CryptoCipherV2 {
42
77
  throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
43
78
  }
44
79
 
45
- return decryptedChecksum.base64EncodedString()
80
+ // Return as hex string to match calcChecksum output format
81
+ let result = decryptedChecksum.map { String(format: "%02x", $0) }.joined()
82
+
83
+ // Detect checksum algorithm based on length
84
+ let detectedAlgorithm: String
85
+ if decryptedChecksum.count == 32 {
86
+ detectedAlgorithm = "SHA-256"
87
+ } else if decryptedChecksum.count == 4 {
88
+ detectedAlgorithm = "CRC32 (deprecated)"
89
+ logger.error("CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums.")
90
+ } else {
91
+ detectedAlgorithm = "unknown (\(decryptedChecksum.count) bytes)"
92
+ logger.error("Unknown checksum algorithm detected with \(decryptedChecksum.count) bytes. Expected SHA-256 (32 bytes).")
93
+ }
94
+ logger.debug("Decrypted checksum: \(detectedAlgorithm) hex format (length: \(result.count) chars, \(decryptedChecksum.count) bytes)")
95
+ return result
46
96
  } catch {
47
97
  logger.error("decryptChecksum fail: \(error.localizedDescription)")
48
98
  throw CustomError.cannotDecode
49
99
  }
50
100
  }
101
+
102
+ /// Detect checksum algorithm based on hex string length.
103
+ /// SHA-256 = 64 hex chars (32 bytes)
104
+ /// CRC32 = 8 hex chars (4 bytes)
105
+ public static func detectChecksumAlgorithm(_ hexChecksum: String) -> String {
106
+ if hexChecksum.isEmpty {
107
+ return "empty"
108
+ }
109
+ let len = hexChecksum.count
110
+ if len == 64 {
111
+ return "SHA-256"
112
+ } else if len == 8 {
113
+ return "CRC32 (deprecated)"
114
+ } else {
115
+ return "unknown (\(len) hex chars)"
116
+ }
117
+ }
118
+
119
+ /// Log checksum info and warn if deprecated algorithm detected.
120
+ public static func logChecksumInfo(label: String, hexChecksum: String) {
121
+ let algorithm = detectChecksumAlgorithm(hexChecksum)
122
+ logger.debug("\(label): \(algorithm) hex format (length: \(hexChecksum.count) chars)")
123
+ if algorithm.contains("CRC32") {
124
+ logger.error("CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums.")
125
+ } else if algorithm.contains("unknown") {
126
+ logger.error("Unknown checksum algorithm detected. Expected SHA-256 (64 hex chars) but got \(hexChecksum.count) chars.")
127
+ }
128
+ }
129
+
51
130
  public static func calcChecksum(filePath: URL) -> String {
52
131
  let bufferSize = 1024 * 1024 * 5 // 5 MB
53
132
  var sha256 = SHA256()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "6.27.11",
3
+ "version": "6.34.0",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",
@@ -1,222 +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
- package ee.forgr.capacitor_updater;
8
-
9
- /**
10
- * Created by Awesometic
11
- * It's encrypt returns Base64 encoded, and also decrypt for Base64 encoded cipher
12
- * references: http://stackoverflow.com/questions/12471999/rsa-encryption-decryption-in-android
13
- *
14
- * V1 Encryption - uses privateKey (deprecated but kept for backwards compatibility)
15
- */
16
- import android.util.Base64;
17
- import android.util.Log;
18
- import java.io.BufferedInputStream;
19
- import java.io.DataInputStream;
20
- import java.io.File;
21
- import java.io.FileInputStream;
22
- import java.io.FileOutputStream;
23
- import java.io.IOException;
24
- import java.security.GeneralSecurityException;
25
- import java.security.InvalidAlgorithmParameterException;
26
- import java.security.InvalidKeyException;
27
- import java.security.KeyFactory;
28
- import java.security.NoSuchAlgorithmException;
29
- import java.security.PrivateKey;
30
- import java.security.PublicKey;
31
- import java.security.spec.InvalidKeySpecException;
32
- import java.security.spec.MGF1ParameterSpec;
33
- import java.security.spec.PKCS8EncodedKeySpec;
34
- import java.security.spec.X509EncodedKeySpec;
35
- import java.util.zip.CRC32;
36
- import javax.crypto.BadPaddingException;
37
- import javax.crypto.Cipher;
38
- import javax.crypto.IllegalBlockSizeException;
39
- import javax.crypto.NoSuchPaddingException;
40
- import javax.crypto.SecretKey;
41
- import javax.crypto.spec.IvParameterSpec;
42
- import javax.crypto.spec.OAEPParameterSpec;
43
- import javax.crypto.spec.PSource;
44
- import javax.crypto.spec.SecretKeySpec;
45
-
46
- public class CryptoCipherV1 {
47
-
48
- private static Logger logger;
49
-
50
- public static void setLogger(Logger loggerInstance) {
51
- logger = loggerInstance;
52
- }
53
-
54
- public static byte[] decryptRSA(byte[] source, PrivateKey privateKey)
55
- throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
56
- Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
57
- OAEPParameterSpec oaepParams = new OAEPParameterSpec(
58
- "SHA-256",
59
- "MGF1",
60
- new MGF1ParameterSpec("SHA-256"),
61
- PSource.PSpecified.DEFAULT
62
- );
63
- cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams);
64
- return cipher.doFinal(source);
65
- }
66
-
67
- public static byte[] decryptAES(byte[] cipherText, SecretKey key, byte[] iv) {
68
- try {
69
- IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
70
- Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
71
- SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
72
- cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
73
- return cipher.doFinal(cipherText);
74
- } catch (Exception e) {
75
- e.printStackTrace();
76
- }
77
- return null;
78
- }
79
-
80
- public static SecretKey byteToSessionKey(byte[] sessionKey) {
81
- // rebuild key using SecretKeySpec
82
- return new SecretKeySpec(sessionKey, 0, sessionKey.length, "AES");
83
- }
84
-
85
- private static PrivateKey readPkcs8PrivateKey(byte[] pkcs8Bytes) throws GeneralSecurityException {
86
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
87
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Bytes);
88
- try {
89
- return keyFactory.generatePrivate(keySpec);
90
- } catch (InvalidKeySpecException e) {
91
- throw new IllegalArgumentException("Unexpected key format!", e);
92
- }
93
- }
94
-
95
- private static byte[] join(byte[] byteArray1, byte[] byteArray2) {
96
- byte[] bytes = new byte[byteArray1.length + byteArray2.length];
97
- System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length);
98
- System.arraycopy(byteArray2, 0, bytes, byteArray1.length, byteArray2.length);
99
- return bytes;
100
- }
101
-
102
- private static PrivateKey readPkcs1PrivateKey(byte[] pkcs1Bytes) throws GeneralSecurityException {
103
- // We can't use Java internal APIs to parse ASN.1 structures, so we build a PKCS#8 key Java can understand
104
- int pkcs1Length = pkcs1Bytes.length;
105
- int totalLength = pkcs1Length + 22;
106
- byte[] pkcs8Header = new byte[] {
107
- 0x30,
108
- (byte) 0x82,
109
- (byte) ((totalLength >> 8) & 0xff),
110
- (byte) (totalLength & 0xff), // Sequence + total length
111
- 0x2,
112
- 0x1,
113
- 0x0, // Integer (0)
114
- 0x30,
115
- 0xD,
116
- 0x6,
117
- 0x9,
118
- 0x2A,
119
- (byte) 0x86,
120
- 0x48,
121
- (byte) 0x86,
122
- (byte) 0xF7,
123
- 0xD,
124
- 0x1,
125
- 0x1,
126
- 0x1,
127
- 0x5,
128
- 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL
129
- 0x4,
130
- (byte) 0x82,
131
- (byte) ((pkcs1Length >> 8) & 0xff),
132
- (byte) (pkcs1Length & 0xff) // Octet string + length
133
- };
134
- byte[] pkcs8bytes = join(pkcs8Header, pkcs1Bytes);
135
- return readPkcs8PrivateKey(pkcs8bytes);
136
- }
137
-
138
- public static PrivateKey stringToPrivateKey(String private_key) throws GeneralSecurityException {
139
- // Base64 decode the result
140
-
141
- String pkcs1Pem = private_key;
142
- pkcs1Pem = pkcs1Pem.replace("-----BEGIN RSA PRIVATE KEY-----", "");
143
- pkcs1Pem = pkcs1Pem.replace("-----END RSA PRIVATE KEY-----", "");
144
- pkcs1Pem = pkcs1Pem.replace("\\n", "");
145
- pkcs1Pem = pkcs1Pem.replace(" ", "");
146
-
147
- byte[] pkcs1EncodedBytes = Base64.decode(pkcs1Pem.getBytes(), Base64.DEFAULT);
148
- // extract the private key
149
- return readPkcs1PrivateKey(pkcs1EncodedBytes);
150
- }
151
-
152
- public static void decryptFile(final File file, final String privateKey, final String ivSessionKey, final String version)
153
- throws IOException {
154
- // (str != null && !str.isEmpty())
155
- if (privateKey == null || privateKey.isEmpty()) {
156
- Log.i("[Capacitor-updater]", "Cannot found privateKey");
157
- return;
158
- } else if (ivSessionKey == null || ivSessionKey.isEmpty() || ivSessionKey.split(":").length != 2) {
159
- Log.i("[Capacitor-updater]", "Cannot found sessionKey");
160
- return;
161
- }
162
- try {
163
- String ivB64 = ivSessionKey.split(":")[0];
164
- String sessionKeyB64 = ivSessionKey.split(":")[1];
165
- byte[] iv = Base64.decode(ivB64.getBytes(), Base64.DEFAULT);
166
- byte[] sessionKey = Base64.decode(sessionKeyB64.getBytes(), Base64.DEFAULT);
167
- PrivateKey pKey = CryptoCipherV1.stringToPrivateKey(privateKey);
168
- byte[] decryptedSessionKey = CryptoCipherV1.decryptRSA(sessionKey, pKey);
169
- SecretKey sKey = CryptoCipherV1.byteToSessionKey(decryptedSessionKey);
170
- byte[] content = new byte[(int) file.length()];
171
-
172
- try (
173
- final FileInputStream fis = new FileInputStream(file);
174
- final BufferedInputStream bis = new BufferedInputStream(fis);
175
- final DataInputStream dis = new DataInputStream(bis)
176
- ) {
177
- dis.readFully(content);
178
- dis.close();
179
- byte[] decrypted = CryptoCipherV1.decryptAES(content, sKey, iv);
180
- // write the decrypted string to the file
181
- try (final FileOutputStream fos = new FileOutputStream(file.getAbsolutePath())) {
182
- fos.write(decrypted);
183
- }
184
- }
185
- } catch (GeneralSecurityException e) {
186
- Log.i("[Capacitor-updater]", "decryptFile fail");
187
- e.printStackTrace();
188
- throw new IOException("GeneralSecurityException");
189
- }
190
- }
191
-
192
- public static String calcChecksum(File file) {
193
- final int BUFFER_SIZE = 1024 * 1024 * 5; // 5 MB buffer size
194
- CRC32 crc = new CRC32();
195
-
196
- try (FileInputStream fis = new FileInputStream(file)) {
197
- byte[] buffer = new byte[BUFFER_SIZE];
198
- int length;
199
- while ((length = fis.read(buffer)) != -1) {
200
- crc.update(buffer, 0, length);
201
- }
202
- return String.format("%08x", crc.getValue());
203
- } catch (IOException e) {
204
- System.err.println("[Capacitor-updater]" + " Cannot calc checksum: " + file.getPath() + " " + e.getMessage());
205
- return "";
206
- }
207
- }
208
-
209
- public static PublicKey stringToPublicKey(String publicKey) {
210
- byte[] encoded = Base64.decode(publicKey, Base64.DEFAULT);
211
-
212
- KeyFactory keyFactory = null;
213
- try {
214
- keyFactory = KeyFactory.getInstance("RSA");
215
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
216
- return keyFactory.generatePublic(keySpec);
217
- } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
218
- Log.i("Capacitor-updater", "stringToPublicKey fail\nError:\n" + e.toString());
219
- return null;
220
- }
221
- }
222
- }
@@ -1,245 +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 zlib
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 RSA keypair. Includes both private and public key.
22
- ///
23
- public struct RSAKeyPair {
24
- private let privateKey: SecKey
25
- private let publicKey: SecKey
26
-
27
- #if DEBUG
28
- public var __debug_privateKey: SecKey { self.privateKey }
29
- public var __debug_publicKey: SecKey { self.publicKey }
30
- #endif
31
-
32
- fileprivate init(privateKey: SecKey, publicKey: SecKey) {
33
- self.privateKey = privateKey
34
- self.publicKey = publicKey
35
- }
36
-
37
- ///
38
- /// Takes the data and uses the private key to decrypt it.
39
- /// Returns the decrypted data.
40
- ///
41
- public func decrypt(data: Data) -> Data? {
42
- var error: Unmanaged<CFError>?
43
- if let decryptedData: CFData = SecKeyCreateDecryptedData(self.privateKey, CryptoCipherConstants.rsaAlgorithm, data as CFData, &error) {
44
- if error != nil {
45
- return nil
46
- } else {
47
- return decryptedData as Data
48
- }
49
- } else {
50
- return nil
51
- }
52
- }
53
-
54
- ///
55
- /// Takes the data and uses the public key to encrypt it.
56
- /// Returns the encrypted data.
57
- ///
58
- public func encrypt(data: Data) -> Data? {
59
- var error: Unmanaged<CFError>?
60
- if let encryptedData: CFData = SecKeyCreateEncryptedData(self.publicKey, CryptoCipherConstants.rsaAlgorithm, data as CFData, &error) {
61
- if error != nil {
62
- return nil
63
- } else {
64
- return encryptedData as Data
65
- }
66
- } else {
67
- return nil
68
- }
69
- }
70
-
71
- }
72
- ///
73
- /// The RSA public key.
74
- ///
75
- public struct RSAPrivateKey {
76
- private let privateKey: SecKey
77
-
78
- #if DEBUG
79
- public var __debug_privateKey: SecKey { self.privateKey }
80
- #endif
81
-
82
- fileprivate init(privateKey: SecKey) {
83
- self.privateKey = privateKey
84
- }
85
- ///
86
- /// Takes the data and uses the private key to decrypt it.
87
- /// Returns the decrypted data.
88
- ///
89
- public func decrypt(data: Data) -> Data? {
90
- var error: Unmanaged<CFError>?
91
- if let decryptedData: CFData = SecKeyCreateDecryptedData(self.privateKey, CryptoCipherConstants.rsaAlgorithm, data as CFData, &error) {
92
- if error != nil {
93
- return nil
94
- } else {
95
- return decryptedData as Data
96
- }
97
- } else {
98
- return nil
99
- }
100
- }
101
-
102
- ///
103
- /// Allows you to export the RSA public key to a format (so you can send over the net).
104
- ///
105
- public func export() -> Data? {
106
- return privateKey.exportToData()
107
- }
108
-
109
- ///
110
- /// Allows you to load an RSA public key (i.e. one downloaded from the net).
111
- ///
112
- public static func load(rsaPrivateKey: String) -> RSAPrivateKey? {
113
- var privKey: String = rsaPrivateKey
114
- privKey = privKey.replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----", with: "")
115
- privKey = privKey.replacingOccurrences(of: "-----END RSA PRIVATE KEY-----", with: "")
116
- privKey = privKey.replacingOccurrences(of: "\\n+", with: "", options: .regularExpression)
117
- privKey = privKey.trimmingCharacters(in: .whitespacesAndNewlines)
118
- do {
119
- guard let rsaPrivateKeyData: Data = Data(base64Encoded: privKey) else {
120
- throw CustomError.cannotDecode
121
- }
122
- guard let privateKey: SecKey = .loadPrivateFromData(rsaPrivateKeyData) else {
123
- throw CustomError.cannotDecode
124
- }
125
- return RSAPrivateKey(privateKey: privateKey)
126
- } catch {
127
- print("Error load RSA: \(error)")
128
- return nil
129
- }
130
- }
131
- }
132
-
133
- fileprivate extension SecKey {
134
- func exportToData() -> Data? {
135
- var error: Unmanaged<CFError>?
136
- if let cfData: CFData = SecKeyCopyExternalRepresentation(self, &error) {
137
- if error != nil {
138
- return nil
139
- } else {
140
- return cfData as Data
141
- }
142
- } else {
143
- return nil
144
- }
145
- }
146
- static func loadPublicFromData(_ data: Data) -> SecKey? {
147
- let keyDict: [NSObject: NSObject] = [
148
- kSecAttrKeyType: kSecAttrKeyTypeRSA,
149
- kSecAttrKeyClass: kSecAttrKeyClassPublic,
150
- kSecAttrKeySizeInBits: CryptoCipherConstants.rsaKeySizeInBits
151
- ]
152
- return SecKeyCreateWithData(data as NSData, keyDict as CFDictionary, nil)
153
- }
154
- static func loadPrivateFromData(_ data: Data) -> SecKey? {
155
- let keyDict: [NSObject: NSObject] = [
156
- kSecAttrKeyType: kSecAttrKeyTypeRSA,
157
- kSecAttrKeyClass: kSecAttrKeyClassPrivate,
158
- kSecAttrKeySizeInBits: CryptoCipherConstants.rsaKeySizeInBits
159
- ]
160
- return SecKeyCreateWithData(data as CFData, keyDict as CFDictionary, nil)
161
- }
162
- }
163
-
164
- // V1 Encryption - uses privateKey (deprecated but kept for backwards compatibility)
165
- public struct CryptoCipherV1 {
166
- private static var logger: Logger?
167
-
168
- public static func setLogger(_ newLogger: Logger) {
169
- logger = newLogger
170
- }
171
-
172
- public static func calcChecksum(filePath: URL) -> String {
173
- let bufferSize = 1024 * 1024 * 5 // 5 MB
174
- var checksum = uLong(0)
175
-
176
- do {
177
- let fileHandle = try FileHandle(forReadingFrom: filePath)
178
- defer {
179
- fileHandle.closeFile()
180
- }
181
-
182
- while autoreleasepool(invoking: {
183
- let fileData = fileHandle.readData(ofLength: bufferSize)
184
- if fileData.count > 0 {
185
- checksum = fileData.withUnsafeBytes {
186
- crc32(checksum, $0.bindMemory(to: Bytef.self).baseAddress, uInt(fileData.count))
187
- }
188
- return true // Continue
189
- } else {
190
- return false // End of file
191
- }
192
- }) {}
193
-
194
- return String(format: "%08X", checksum).lowercased()
195
- } catch {
196
- print("\("[Capacitor-updater]") Cannot get checksum: \(filePath.path)", error)
197
- return ""
198
- }
199
- }
200
- public static func decryptFile(filePath: URL, privateKey: String, sessionKey: String, version: String) throws {
201
- if privateKey.isEmpty {
202
- print("\("[Capacitor-updater]") Cannot found privateKey")
203
- return
204
- } else if sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
205
- print("\("[Capacitor-updater]") Cannot found sessionKey")
206
- return
207
- }
208
- do {
209
- guard let rsaPrivateKey: RSAPrivateKey = .load(rsaPrivateKey: privateKey) else {
210
- print("cannot decode privateKey", privateKey)
211
- throw CustomError.cannotDecode
212
- }
213
-
214
- let sessionKeyArray: [String] = sessionKey.components(separatedBy: ":")
215
- guard let ivData: Data = Data(base64Encoded: sessionKeyArray[0]) else {
216
- print("cannot decode sessionKey", sessionKey)
217
- throw CustomError.cannotDecode
218
- }
219
-
220
- guard let sessionKeyDataEncrypted = Data(base64Encoded: sessionKeyArray[1]) else {
221
- throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
222
- }
223
-
224
- guard let sessionKeyDataDecrypted = rsaPrivateKey.decrypt(data: sessionKeyDataEncrypted) else {
225
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
226
- }
227
-
228
- let aesPrivateKey = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted, logger: logger ?? Logger(withTag: "[Capacitor-updater]"))
229
-
230
- guard let encryptedData = try? Data(contentsOf: filePath) else {
231
- throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
232
- }
233
-
234
- guard let decryptedData = aesPrivateKey.decrypt(data: encryptedData) else {
235
- throw NSError(domain: "Failed to decrypt data", code: 4, userInfo: nil)
236
- }
237
-
238
- try decryptedData.write(to: filePath)
239
-
240
- } catch {
241
- print("\("[Capacitor-updater]") Cannot decode: \(filePath.path)", error)
242
- throw CustomError.cannotDecode
243
- }
244
- }
245
- }