@hot-updater/react-native 0.22.1 → 0.23.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.
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +17 -12
- package/android/src/main/java/com/hotupdater/HotUpdater.kt +1 -1
- package/android/src/main/java/com/hotupdater/HotUpdaterFactory.kt +1 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +1 -1
- package/android/src/main/java/com/hotupdater/SignatureVerifier.kt +346 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +26 -18
- package/ios/HotUpdater/Internal/SignatureVerifier.swift +339 -0
- package/lib/commonjs/checkForUpdate.js +1 -1
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/index.js +16 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/types.js +45 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/checkForUpdate.js +1 -1
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/types.js +40 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +7 -2
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +34 -0
- package/lib/typescript/commonjs/types.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +7 -2
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +34 -0
- package/lib/typescript/module/types.d.ts.map +1 -0
- package/package.json +7 -7
- package/plugin/build/transformers.js +269 -0
- package/src/checkForUpdate.ts +1 -1
- package/src/index.ts +5 -0
- package/src/specs/NativeHotUpdater.ts +7 -2
- package/src/types.ts +63 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Security
|
|
3
|
+
|
|
4
|
+
/// Prefix for signed file hash format.
|
|
5
|
+
private let SIGNED_HASH_PREFIX = "sig:"
|
|
6
|
+
|
|
7
|
+
/// Error types for signature verification failures.
|
|
8
|
+
///
|
|
9
|
+
/// **IMPORTANT**: The error messages in `errorUserInfo` are used by the JavaScript layer
|
|
10
|
+
/// (`packages/react-native/src/types.ts`) to detect signature verification failures.
|
|
11
|
+
/// If you change these messages, update `isSignatureVerificationError()` in types.ts accordingly.
|
|
12
|
+
public enum SignatureVerificationError: Error, CustomNSError {
|
|
13
|
+
case publicKeyNotConfigured
|
|
14
|
+
case invalidPublicKeyFormat
|
|
15
|
+
case invalidSignatureFormat
|
|
16
|
+
case verificationFailed
|
|
17
|
+
case hashMismatch
|
|
18
|
+
case hashCalculationFailed
|
|
19
|
+
case unsignedNotAllowed
|
|
20
|
+
case securityFrameworkError(OSStatus)
|
|
21
|
+
|
|
22
|
+
// CustomNSError protocol implementation
|
|
23
|
+
public static var errorDomain: String {
|
|
24
|
+
return "com.hotupdater.SignatureVerificationError"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public var errorCode: Int {
|
|
28
|
+
switch self {
|
|
29
|
+
case .publicKeyNotConfigured: return 2001
|
|
30
|
+
case .invalidPublicKeyFormat: return 2002
|
|
31
|
+
case .invalidSignatureFormat: return 2003
|
|
32
|
+
case .verificationFailed: return 2004
|
|
33
|
+
case .hashMismatch: return 2005
|
|
34
|
+
case .hashCalculationFailed: return 2006
|
|
35
|
+
case .unsignedNotAllowed: return 2007
|
|
36
|
+
case .securityFrameworkError: return 2099
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public var errorUserInfo: [String: Any] {
|
|
41
|
+
var userInfo: [String: Any] = [:]
|
|
42
|
+
|
|
43
|
+
switch self {
|
|
44
|
+
case .publicKeyNotConfigured:
|
|
45
|
+
userInfo[NSLocalizedDescriptionKey] = "Public key not configured for signature verification"
|
|
46
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "Add HOT_UPDATER_PUBLIC_KEY to Info.plist with your RSA public key"
|
|
47
|
+
|
|
48
|
+
case .invalidPublicKeyFormat:
|
|
49
|
+
userInfo[NSLocalizedDescriptionKey] = "Public key format is invalid"
|
|
50
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "Ensure the public key is in PEM format (BEGIN PUBLIC KEY)"
|
|
51
|
+
|
|
52
|
+
case .invalidSignatureFormat:
|
|
53
|
+
userInfo[NSLocalizedDescriptionKey] = "Signature format is invalid"
|
|
54
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "The signature must be base64-encoded"
|
|
55
|
+
|
|
56
|
+
case .verificationFailed:
|
|
57
|
+
userInfo[NSLocalizedDescriptionKey] = "Bundle signature verification failed"
|
|
58
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "The bundle may be corrupted or tampered with. Rejecting update for security"
|
|
59
|
+
|
|
60
|
+
case .hashMismatch:
|
|
61
|
+
userInfo[NSLocalizedDescriptionKey] = "Bundle hash verification failed"
|
|
62
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "The bundle file hash does not match. File may be corrupted"
|
|
63
|
+
|
|
64
|
+
case .hashCalculationFailed:
|
|
65
|
+
userInfo[NSLocalizedDescriptionKey] = "Failed to calculate file hash"
|
|
66
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "Could not read file for hash verification"
|
|
67
|
+
|
|
68
|
+
case .unsignedNotAllowed:
|
|
69
|
+
userInfo[NSLocalizedDescriptionKey] = "Unsigned bundle not allowed when signing is enabled"
|
|
70
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "Public key is configured but bundle is not signed. Rejecting update"
|
|
71
|
+
|
|
72
|
+
case .securityFrameworkError(let status):
|
|
73
|
+
userInfo[NSLocalizedDescriptionKey] = "Security framework error during verification (OSStatus: \(status))"
|
|
74
|
+
userInfo[NSLocalizedRecoverySuggestionErrorKey] = "Check public key format and signature data"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return userInfo
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Service for verifying bundle integrity through hash or RSA-SHA256 signature verification.
|
|
83
|
+
* Uses iOS Security framework for cryptographic operations.
|
|
84
|
+
*
|
|
85
|
+
* fileHash format:
|
|
86
|
+
* - Signed: `sig:<base64_signature>` - Verify signature (implicitly verifies hash)
|
|
87
|
+
* - Unsigned: `<hex_hash>` - Verify SHA256 hash only
|
|
88
|
+
*
|
|
89
|
+
* Security rules:
|
|
90
|
+
* - null/empty fileHash → REJECT
|
|
91
|
+
* - sig:... + public key configured → verify signature → Install/REJECT
|
|
92
|
+
* - sig:... + public key NOT configured → REJECT (can't verify)
|
|
93
|
+
* - <hash> + public key configured → REJECT (unsigned not allowed)
|
|
94
|
+
* - <hash> + public key NOT configured → verify hash → Install/REJECT
|
|
95
|
+
*/
|
|
96
|
+
public class SignatureVerifier {
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Reads public key from Info.plist configuration.
|
|
100
|
+
* @return Public key PEM string or nil if not configured
|
|
101
|
+
*/
|
|
102
|
+
private static func getPublicKeyFromConfig() -> String? {
|
|
103
|
+
guard let publicKeyPEM = Bundle.main.object(forInfoDictionaryKey: "HOT_UPDATER_PUBLIC_KEY") as? String else {
|
|
104
|
+
NSLog("[SignatureVerifier] HOT_UPDATER_PUBLIC_KEY not found in Info.plist")
|
|
105
|
+
return nil
|
|
106
|
+
}
|
|
107
|
+
return publicKeyPEM
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if signing is enabled (public key is configured).
|
|
112
|
+
* @return true if public key is configured
|
|
113
|
+
*/
|
|
114
|
+
public static func isSigningEnabled() -> Bool {
|
|
115
|
+
return getPublicKeyFromConfig() != nil
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Checks if fileHash is in signed format (starts with "sig:").
|
|
120
|
+
* @param fileHash The file hash string to check
|
|
121
|
+
* @return true if signed format
|
|
122
|
+
*/
|
|
123
|
+
public static func isSignedFormat(_ fileHash: String?) -> Bool {
|
|
124
|
+
guard let hash = fileHash else { return false }
|
|
125
|
+
return hash.hasPrefix(SIGNED_HASH_PREFIX)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Extracts signature from signed format fileHash.
|
|
130
|
+
* @param fileHash The signed file hash (sig:<signature>)
|
|
131
|
+
* @return Base64-encoded signature or nil if not signed format
|
|
132
|
+
*/
|
|
133
|
+
public static func extractSignature(_ fileHash: String?) -> String? {
|
|
134
|
+
guard let hash = fileHash, isSignedFormat(hash) else { return nil }
|
|
135
|
+
return String(hash.dropFirst(SIGNED_HASH_PREFIX.count))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Verifies bundle integrity based on fileHash format.
|
|
140
|
+
* Determines verification mode by checking for "sig:" prefix.
|
|
141
|
+
*
|
|
142
|
+
* @param fileURL URL of the bundle file to verify
|
|
143
|
+
* @param fileHash Combined hash string (sig:<signature> or <hex_hash>)
|
|
144
|
+
* @return Result indicating verification success or failure with error
|
|
145
|
+
*/
|
|
146
|
+
public static func verifyBundle(fileURL: URL, fileHash: String?) -> Result<Void, SignatureVerificationError> {
|
|
147
|
+
let signingEnabled = isSigningEnabled()
|
|
148
|
+
|
|
149
|
+
// Rule: null/empty fileHash → REJECT
|
|
150
|
+
guard let hash = fileHash, !hash.isEmpty else {
|
|
151
|
+
NSLog("[SignatureVerifier] fileHash is null or empty. Rejecting update.")
|
|
152
|
+
return .failure(.verificationFailed)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if isSignedFormat(hash) {
|
|
156
|
+
// Signed format: sig:<signature>
|
|
157
|
+
guard let signature = extractSignature(hash) else {
|
|
158
|
+
NSLog("[SignatureVerifier] Failed to extract signature from fileHash")
|
|
159
|
+
return .failure(.invalidSignatureFormat)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Rule: sig:... + public key NOT configured → REJECT
|
|
163
|
+
guard signingEnabled else {
|
|
164
|
+
NSLog("[SignatureVerifier] Signed bundle but public key not configured. Cannot verify.")
|
|
165
|
+
return .failure(.publicKeyNotConfigured)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Rule: sig:... + public key configured → verify signature
|
|
169
|
+
return verifySignature(fileURL: fileURL, signatureBase64: signature)
|
|
170
|
+
} else {
|
|
171
|
+
// Unsigned format: <hex_hash>
|
|
172
|
+
|
|
173
|
+
// Rule: <hash> + public key configured → REJECT
|
|
174
|
+
if signingEnabled {
|
|
175
|
+
NSLog("[SignatureVerifier] Unsigned bundle not allowed when signing is enabled. Rejecting.")
|
|
176
|
+
return .failure(.unsignedNotAllowed)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Rule: <hash> + public key NOT configured → verify hash
|
|
180
|
+
return verifyHash(fileURL: fileURL, expectedHash: hash)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Verifies SHA256 hash of a file.
|
|
186
|
+
* @param fileURL URL of the file to verify
|
|
187
|
+
* @param expectedHash Expected SHA256 hash (hex string)
|
|
188
|
+
* @return Result indicating verification success or failure
|
|
189
|
+
*/
|
|
190
|
+
public static func verifyHash(fileURL: URL, expectedHash: String) -> Result<Void, SignatureVerificationError> {
|
|
191
|
+
NSLog("[SignatureVerifier] Verifying hash for file: \(fileURL.lastPathComponent)")
|
|
192
|
+
|
|
193
|
+
guard HashUtils.verifyHash(fileURL: fileURL, expectedHash: expectedHash) else {
|
|
194
|
+
NSLog("[SignatureVerifier] Hash mismatch!")
|
|
195
|
+
return .failure(.hashMismatch)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
NSLog("[SignatureVerifier] ✅ Hash verified successfully")
|
|
199
|
+
return .success(())
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Verifies RSA-SHA256 signature of a file.
|
|
204
|
+
* Calculates the file hash internally and verifies the signature.
|
|
205
|
+
*
|
|
206
|
+
* @param fileURL URL of the file to verify
|
|
207
|
+
* @param signatureBase64 Base64-encoded RSA-SHA256 signature
|
|
208
|
+
* @return Result indicating verification success or failure with error
|
|
209
|
+
*/
|
|
210
|
+
public static func verifySignature(fileURL: URL, signatureBase64: String) -> Result<Void, SignatureVerificationError> {
|
|
211
|
+
NSLog("[SignatureVerifier] Verifying signature for file: \(fileURL.lastPathComponent)")
|
|
212
|
+
|
|
213
|
+
// Get public key from config
|
|
214
|
+
guard let publicKeyPEM = getPublicKeyFromConfig() else {
|
|
215
|
+
NSLog("[SignatureVerifier] Cannot verify signature: public key not configured in Info.plist")
|
|
216
|
+
return .failure(.publicKeyNotConfigured)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Convert PEM to SecKey
|
|
220
|
+
let publicKeyResult = createPublicKey(from: publicKeyPEM)
|
|
221
|
+
guard case .success(let publicKey) = publicKeyResult else {
|
|
222
|
+
if case .failure(let error) = publicKeyResult {
|
|
223
|
+
return .failure(error)
|
|
224
|
+
}
|
|
225
|
+
return .failure(.invalidPublicKeyFormat)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Calculate file hash
|
|
229
|
+
guard let fileHashHex = HashUtils.calculateSHA256(fileURL: fileURL) else {
|
|
230
|
+
NSLog("[SignatureVerifier] Failed to calculate file hash")
|
|
231
|
+
return .failure(.hashCalculationFailed)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
NSLog("[SignatureVerifier] Calculated file hash: \(fileHashHex)")
|
|
235
|
+
|
|
236
|
+
// Decode signature from base64
|
|
237
|
+
guard let signatureData = Data(base64Encoded: signatureBase64) else {
|
|
238
|
+
NSLog("[SignatureVerifier] Failed to decode signature from base64")
|
|
239
|
+
return .failure(.invalidSignatureFormat)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Convert hex fileHash to data
|
|
243
|
+
guard let fileHashData = dataFromHexString(fileHashHex) else {
|
|
244
|
+
NSLog("[SignatureVerifier] Failed to convert fileHash from hex")
|
|
245
|
+
return .failure(.invalidSignatureFormat)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Verify signature
|
|
249
|
+
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA256
|
|
250
|
+
|
|
251
|
+
guard SecKeyIsAlgorithmSupported(publicKey, .verify, algorithm) else {
|
|
252
|
+
NSLog("[SignatureVerifier] RSA-SHA256 algorithm not supported")
|
|
253
|
+
return .failure(.securityFrameworkError(-1))
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
var error: Unmanaged<CFError>?
|
|
257
|
+
let verified = SecKeyVerifySignature(
|
|
258
|
+
publicKey,
|
|
259
|
+
algorithm,
|
|
260
|
+
fileHashData as CFData,
|
|
261
|
+
signatureData as CFData,
|
|
262
|
+
&error
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if let err = error?.takeRetainedValue() {
|
|
266
|
+
NSLog("[SignatureVerifier] Verification failed: \(err)")
|
|
267
|
+
return .failure(.verificationFailed)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if verified {
|
|
271
|
+
NSLog("[SignatureVerifier] ✅ Signature verified successfully")
|
|
272
|
+
return .success(())
|
|
273
|
+
} else {
|
|
274
|
+
NSLog("[SignatureVerifier] ❌ Signature verification failed")
|
|
275
|
+
return .failure(.verificationFailed)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Converts PEM-formatted public key to SecKey.
|
|
281
|
+
* @param publicKeyPEM Public key in PEM format
|
|
282
|
+
* @return SecKey or error
|
|
283
|
+
*/
|
|
284
|
+
private static func createPublicKey(from publicKeyPEM: String) -> Result<SecKey, SignatureVerificationError> {
|
|
285
|
+
// Remove PEM headers/footers and whitespace
|
|
286
|
+
var keyString = publicKeyPEM
|
|
287
|
+
.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
|
|
288
|
+
.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
|
|
289
|
+
.replacingOccurrences(of: "\\n", with: "")
|
|
290
|
+
.replacingOccurrences(of: "\n", with: "")
|
|
291
|
+
.replacingOccurrences(of: " ", with: "")
|
|
292
|
+
|
|
293
|
+
// Decode base64
|
|
294
|
+
guard let keyData = Data(base64Encoded: keyString) else {
|
|
295
|
+
NSLog("[SignatureVerifier] Failed to decode public key from base64")
|
|
296
|
+
return .failure(.invalidPublicKeyFormat)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// SecKeyCreateWithData auto-detects key size from SPKI-formatted key data.
|
|
300
|
+
// This supports any valid RSA key size (2048, 3072, 4096-bit, etc.)
|
|
301
|
+
let attributes: [String: Any] = [
|
|
302
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
|
|
303
|
+
kSecAttrKeyClass as String: kSecAttrKeyClassPublic
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
var error: Unmanaged<CFError>?
|
|
307
|
+
guard let secKey = SecKeyCreateWithData(keyData as CFData, attributes as CFDictionary, &error) else {
|
|
308
|
+
if let err = error?.takeRetainedValue() {
|
|
309
|
+
NSLog("[SignatureVerifier] SecKeyCreateWithData failed: \(err)")
|
|
310
|
+
}
|
|
311
|
+
return .failure(.invalidPublicKeyFormat)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return .success(secKey)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Converts hex string to Data.
|
|
319
|
+
* @param hexString Hex-encoded string
|
|
320
|
+
* @return Data or nil if invalid format
|
|
321
|
+
*/
|
|
322
|
+
private static func dataFromHexString(_ hexString: String) -> Data? {
|
|
323
|
+
var data = Data(capacity: hexString.count / 2)
|
|
324
|
+
|
|
325
|
+
var index = hexString.startIndex
|
|
326
|
+
while index < hexString.endIndex {
|
|
327
|
+
let nextIndex = hexString.index(index, offsetBy: 2)
|
|
328
|
+
guard nextIndex <= hexString.endIndex else { return nil }
|
|
329
|
+
|
|
330
|
+
let byteString = hexString[index..<nextIndex]
|
|
331
|
+
guard let byte = UInt8(byteString, radix: 16) else { return nil }
|
|
332
|
+
|
|
333
|
+
data.append(byte)
|
|
334
|
+
index = nextIndex
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return data
|
|
338
|
+
}
|
|
339
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_error","_fetchUpdateInfo","_native","checkForUpdate","options","__DEV__","includes","Platform","OS","onError","HotUpdaterError","currentAppVersion","getAppVersion","platform","currentBundleId","getBundleId","minBundleId","getMinBundleId","channel","getChannel","fingerprintHash","getFingerprintHash","fetchUpdateInfo","source","params","bundleId","appVersion","requestHeaders","requestTimeout","then","updateInfo","updateBundle","id","fileUrl","fileHash","status","getUpdateSource","baseUrl","updateStrategy","exports"],"sourceRoot":"../../src","sources":["checkForUpdate.ts"],"mappings":";;;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,gBAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AA4BO,eAAeI,cAAcA,CAClCC,OAA8B,EACQ;EACtC,IAAIC,OAAO,EAAE;IACX,OAAO,IAAI;EACb;EAEA,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAACC,QAAQ,CAACC,qBAAQ,CAACC,EAAE,CAAC,EAAE;IAC7CJ,OAAO,CAACK,OAAO,GACb,IAAIC,sBAAe,CAAC,iDAAiD,CACvE,CAAC;IACD,OAAO,IAAI;EACb;EAEA,MAAMC,iBAAiB,GAAG,IAAAC,qBAAa,EAAC,CAAC;EACzC,MAAMC,QAAQ,GAAGN,qBAAQ,CAACC,EAAuB;EACjD,MAAMM,eAAe,GAAG,IAAAC,mBAAW,EAAC,CAAC;EACrC,MAAMC,WAAW,GAAG,IAAAC,sBAAc,EAAC,CAAC;EACpC,MAAMC,OAAO,GAAG,IAAAC,kBAAU,EAAC,CAAC;EAE5B,IAAI,CAACR,iBAAiB,EAAE;IACtBP,OAAO,CAACK,OAAO,GAAG,IAAIC,sBAAe,CAAC,2BAA2B,CAAC,CAAC;IACnE,OAAO,IAAI;EACb;EAEA,MAAMU,eAAe,GAAG,IAAAC,0BAAkB,EAAC,CAAC;EAE5C,OAAO,IAAAC,gCAAe,EAAC;IACrBC,MAAM,EAAEnB,OAAO,CAACmB,MAAM;IACtBC,MAAM,EAAE;MACNC,QAAQ,EAAEX,eAAe;MACzBY,UAAU,EAAEf,iBAAiB;MAC7BE,QAAQ;MACRG,WAAW;MACXE,OAAO;MACPE;IACF,CAAC;IACDO,cAAc,EAAEvB,OAAO,CAACuB,cAAc;IACtClB,OAAO,EAAEL,OAAO,CAACK,OAAO;IACxBmB,cAAc,EAAExB,OAAO,CAACwB;EAC1B,CAAC,CAAC,CAACC,IAAI,CAAEC,UAAU,IAAK;IACtB,IAAI,CAACA,UAAU,EAAE;MACf,OAAO,IAAI;IACb;IAEA,OAAO;MACL,GAAGA,UAAU;MACbC,YAAY,EAAE,MAAAA,CAAA,KAAY;QACxB,OAAO,IAAAA,oBAAY,EAAC;UAClBN,QAAQ,EAAEK,UAAU,CAACE,EAAE;UACvBC,OAAO,EAAEH,UAAU,CAACG,OAAO;UAC3BC,QAAQ,EAAEJ,UAAU,
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_error","_fetchUpdateInfo","_native","checkForUpdate","options","__DEV__","includes","Platform","OS","onError","HotUpdaterError","currentAppVersion","getAppVersion","platform","currentBundleId","getBundleId","minBundleId","getMinBundleId","channel","getChannel","fingerprintHash","getFingerprintHash","fetchUpdateInfo","source","params","bundleId","appVersion","requestHeaders","requestTimeout","then","updateInfo","updateBundle","id","fileUrl","fileHash","status","getUpdateSource","baseUrl","updateStrategy","exports"],"sourceRoot":"../../src","sources":["checkForUpdate.ts"],"mappings":";;;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,gBAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AA4BO,eAAeI,cAAcA,CAClCC,OAA8B,EACQ;EACtC,IAAIC,OAAO,EAAE;IACX,OAAO,IAAI;EACb;EAEA,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAACC,QAAQ,CAACC,qBAAQ,CAACC,EAAE,CAAC,EAAE;IAC7CJ,OAAO,CAACK,OAAO,GACb,IAAIC,sBAAe,CAAC,iDAAiD,CACvE,CAAC;IACD,OAAO,IAAI;EACb;EAEA,MAAMC,iBAAiB,GAAG,IAAAC,qBAAa,EAAC,CAAC;EACzC,MAAMC,QAAQ,GAAGN,qBAAQ,CAACC,EAAuB;EACjD,MAAMM,eAAe,GAAG,IAAAC,mBAAW,EAAC,CAAC;EACrC,MAAMC,WAAW,GAAG,IAAAC,sBAAc,EAAC,CAAC;EACpC,MAAMC,OAAO,GAAG,IAAAC,kBAAU,EAAC,CAAC;EAE5B,IAAI,CAACR,iBAAiB,EAAE;IACtBP,OAAO,CAACK,OAAO,GAAG,IAAIC,sBAAe,CAAC,2BAA2B,CAAC,CAAC;IACnE,OAAO,IAAI;EACb;EAEA,MAAMU,eAAe,GAAG,IAAAC,0BAAkB,EAAC,CAAC;EAE5C,OAAO,IAAAC,gCAAe,EAAC;IACrBC,MAAM,EAAEnB,OAAO,CAACmB,MAAM;IACtBC,MAAM,EAAE;MACNC,QAAQ,EAAEX,eAAe;MACzBY,UAAU,EAAEf,iBAAiB;MAC7BE,QAAQ;MACRG,WAAW;MACXE,OAAO;MACPE;IACF,CAAC;IACDO,cAAc,EAAEvB,OAAO,CAACuB,cAAc;IACtClB,OAAO,EAAEL,OAAO,CAACK,OAAO;IACxBmB,cAAc,EAAExB,OAAO,CAACwB;EAC1B,CAAC,CAAC,CAACC,IAAI,CAAEC,UAAU,IAAK;IACtB,IAAI,CAACA,UAAU,EAAE;MACf,OAAO,IAAI;IACb;IAEA,OAAO;MACL,GAAGA,UAAU;MACbC,YAAY,EAAE,MAAAA,CAAA,KAAY;QACxB,OAAO,IAAAA,oBAAY,EAAC;UAClBN,QAAQ,EAAEK,UAAU,CAACE,EAAE;UACvBC,OAAO,EAAEH,UAAU,CAACG,OAAO;UAC3BC,QAAQ,EAAEJ,UAAU,CAACI,QAAQ;UAC7BC,MAAM,EAAEL,UAAU,CAACK;QACrB,CAAC,CAAC;MACJ;IACF,CAAC;EACH,CAAC,CAAC;AACJ;AAYO,MAAMC,eAAe,GAC1BA,CAACC,OAAe,EAAEjC,OAA+B,KAChDoB,MAA0B,IAAK;EAC9B,QAAQpB,OAAO,CAACkC,cAAc;IAC5B,KAAK,aAAa;MAAE;QAClB,IAAI,CAACd,MAAM,CAACJ,eAAe,EAAE;UAC3B,MAAM,IAAIV,sBAAe,CAAC,8BAA8B,CAAC;QAC3D;QACA,OAAO,GAAG2B,OAAO,gBAAgBb,MAAM,CAACX,QAAQ,IAAIW,MAAM,CAACJ,eAAe,IAAII,MAAM,CAACN,OAAO,IAAIM,MAAM,CAACR,WAAW,IAAIQ,MAAM,CAACC,QAAQ,EAAE;MACzI;IACA,KAAK,YAAY;MAAE;QACjB,OAAO,GAAGY,OAAO,gBAAgBb,MAAM,CAACX,QAAQ,IAAIW,MAAM,CAACE,UAAU,IAAIF,MAAM,CAACN,OAAO,IAAIM,MAAM,CAACR,WAAW,IAAIQ,MAAM,CAACC,QAAQ,EAAE;MACpI;IACA;MACE,OAAOY,OAAO;EAClB;AACF,CAAC;AAACE,OAAA,CAAAH,eAAA,GAAAA,eAAA","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -5,15 +5,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
var _exportNames = {
|
|
7
7
|
HotUpdater: true,
|
|
8
|
-
getUpdateSource: true
|
|
8
|
+
getUpdateSource: true,
|
|
9
|
+
extractSignatureFailure: true,
|
|
10
|
+
isSignatureVerificationError: true
|
|
9
11
|
};
|
|
10
12
|
exports.HotUpdater = void 0;
|
|
13
|
+
Object.defineProperty(exports, "extractSignatureFailure", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _types.extractSignatureFailure;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
11
19
|
Object.defineProperty(exports, "getUpdateSource", {
|
|
12
20
|
enumerable: true,
|
|
13
21
|
get: function () {
|
|
14
22
|
return _checkForUpdate.getUpdateSource;
|
|
15
23
|
}
|
|
16
24
|
});
|
|
25
|
+
Object.defineProperty(exports, "isSignatureVerificationError", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return _types.isSignatureVerificationError;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
17
31
|
var _checkForUpdate = require("./checkForUpdate.js");
|
|
18
32
|
var _native = require("./native.js");
|
|
19
33
|
var _runUpdateProcess = require("./runUpdateProcess.js");
|
|
@@ -30,6 +44,7 @@ Object.keys(_store).forEach(function (key) {
|
|
|
30
44
|
});
|
|
31
45
|
});
|
|
32
46
|
var _wrap = require("./wrap.js");
|
|
47
|
+
var _types = require("./types.js");
|
|
33
48
|
(0, _native.addListener)("onProgress", ({
|
|
34
49
|
progress
|
|
35
50
|
}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_checkForUpdate","require","_native","_runUpdateProcess","_store","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_wrap","addListener","progress","hotUpdaterStore","setState","HotUpdater","wrap","reload","isUpdateDownloaded","getSnapshot","getAppVersion","getBundleId","getMinBundleId","getChannel","checkForUpdate","runUpdateProcess","updateBundle","getFingerprintHash"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_checkForUpdate","require","_native","_runUpdateProcess","_store","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_wrap","_types","addListener","progress","hotUpdaterStore","setState","HotUpdater","wrap","reload","isUpdateDownloaded","getSnapshot","getAppVersion","getBundleId","getMinBundleId","getChannel","checkForUpdate","runUpdateProcess","updateBundle","getFingerprintHash"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,eAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AAUA,IAAAE,iBAAA,GAAAF,OAAA;AACA,IAAAG,MAAA,GAAAH,OAAA;AAIAI,MAAA,CAAAC,IAAA,CAAAF,MAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,MAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,MAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAHA,IAAAS,KAAA,GAAAhB,OAAA;AAIA,IAAAiB,MAAA,GAAAjB,OAAA;AAOA,IAAAkB,mBAAW,EAAC,YAAY,EAAE,CAAC;EAAEC;AAAS,CAAC,KAAK;EAC1CC,sBAAe,CAACC,QAAQ,CAAC;IACvBF;EACF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEK,MAAMG,UAAU,GAAAV,OAAA,CAAAU,UAAA,GAAG;EACxB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,IAAI,EAAJA,UAAI;EACJ;AACF;AACA;EACEC,MAAM,EAANA,cAAM;EACN;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,kBAAkB,EAAEA,CAAA,KAAML,sBAAe,CAACM,WAAW,CAAC,CAAC,CAACD,kBAAkB;EAC1E;AACF;AACA;EACEE,aAAa,EAAbA,qBAAa;EACb;AACF;AACA;EACEC,WAAW,EAAXA,mBAAW;EACX;AACF;AACA;EACEC,cAAc,EAAdA,sBAAc;EACd;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,UAAU,EAAVA,kBAAU;EACV;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEZ,WAAW,EAAXA,mBAAW;EACX;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEa,cAAc,EAAdA,8BAAc;EACd;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgB,EAAhBA,kCAAgB;EAChB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,YAAY,EAAZA,oBAAY;EACZ;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,kBAAkB,EAAlBA;AACF,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../../src","sources":["specs/NativeHotUpdater.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../../src","sources":["specs/NativeHotUpdater.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAiCpCC,gCAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.extractSignatureFailure = extractSignatureFailure;
|
|
7
|
+
exports.isSignatureVerificationError = isSignatureVerificationError;
|
|
8
|
+
/**
|
|
9
|
+
* Information about a signature verification failure.
|
|
10
|
+
* This is a security-critical event that indicates the bundle
|
|
11
|
+
* may have been tampered with or the public key is misconfigured.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Checks if an error is a signature verification failure.
|
|
16
|
+
* Matches error messages from both iOS and Android native implementations.
|
|
17
|
+
*
|
|
18
|
+
* **IMPORTANT**: This function relies on specific error message patterns from native code.
|
|
19
|
+
* If you change the error messages in the native implementations, update these patterns:
|
|
20
|
+
* - iOS: `ios/HotUpdater/Internal/SignatureVerifier.swift` (SignatureVerificationError)
|
|
21
|
+
* - Android: `android/src/main/java/com/hotupdater/SignatureVerifier.kt` (SignatureVerificationException)
|
|
22
|
+
*/
|
|
23
|
+
function isSignatureVerificationError(error) {
|
|
24
|
+
if (!(error instanceof Error)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const message = error.message.toLowerCase();
|
|
28
|
+
|
|
29
|
+
// Match iOS SignatureVerificationError messages
|
|
30
|
+
// Match Android SignatureVerificationException messages
|
|
31
|
+
return message.includes("signature verification") || message.includes("public key not configured") || message.includes("public key format is invalid") || message.includes("signature format is invalid") || message.includes("bundle may be corrupted or tampered");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extracts signature verification failure details from an error.
|
|
36
|
+
*/
|
|
37
|
+
function extractSignatureFailure(error, bundleId) {
|
|
38
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
39
|
+
return {
|
|
40
|
+
bundleId,
|
|
41
|
+
message: normalizedError.message,
|
|
42
|
+
error: normalizedError
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["isSignatureVerificationError","error","Error","message","toLowerCase","includes","extractSignatureFailure","bundleId","normalizedError","String"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,4BAA4BA,CAACC,KAAc,EAAW;EACpE,IAAI,EAAEA,KAAK,YAAYC,KAAK,CAAC,EAAE;IAC7B,OAAO,KAAK;EACd;EAEA,MAAMC,OAAO,GAAGF,KAAK,CAACE,OAAO,CAACC,WAAW,CAAC,CAAC;;EAE3C;EACA;EACA,OACED,OAAO,CAACE,QAAQ,CAAC,wBAAwB,CAAC,IAC1CF,OAAO,CAACE,QAAQ,CAAC,2BAA2B,CAAC,IAC7CF,OAAO,CAACE,QAAQ,CAAC,8BAA8B,CAAC,IAChDF,OAAO,CAACE,QAAQ,CAAC,6BAA6B,CAAC,IAC/CF,OAAO,CAACE,QAAQ,CAAC,qCAAqC,CAAC;AAE3D;;AAEA;AACA;AACA;AACO,SAASC,uBAAuBA,CACrCL,KAAc,EACdM,QAAgB,EACc;EAC9B,MAAMC,eAAe,GACnBP,KAAK,YAAYC,KAAK,GAAGD,KAAK,GAAG,IAAIC,KAAK,CAACO,MAAM,CAACR,KAAK,CAAC,CAAC;EAE3D,OAAO;IACLM,QAAQ;IACRJ,OAAO,EAAEK,eAAe,CAACL,OAAO;IAChCF,KAAK,EAAEO;EACT,CAAC;AACH","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","HotUpdaterError","fetchUpdateInfo","getAppVersion","getBundleId","getChannel","getFingerprintHash","getMinBundleId","updateBundle","checkForUpdate","options","__DEV__","includes","OS","onError","currentAppVersion","platform","currentBundleId","minBundleId","channel","fingerprintHash","source","params","bundleId","appVersion","requestHeaders","requestTimeout","then","updateInfo","id","fileUrl","fileHash","status","getUpdateSource","baseUrl","updateStrategy"],"sourceRoot":"../../src","sources":["checkForUpdate.ts"],"mappings":";;AACA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,eAAe,QAAQ,YAAS;AACzC,SAASC,eAAe,QAA2B,sBAAmB;AACtE,SACEC,aAAa,EACbC,WAAW,EACXC,UAAU,EACVC,kBAAkB,EAClBC,cAAc,EACdC,YAAY,QACP,aAAU;AAqBjB,OAAO,eAAeC,cAAcA,CAClCC,OAA8B,EACQ;EACtC,IAAIC,OAAO,EAAE;IACX,OAAO,IAAI;EACb;EAEA,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAACC,QAAQ,CAACZ,QAAQ,CAACa,EAAE,CAAC,EAAE;IAC7CH,OAAO,CAACI,OAAO,GACb,IAAIb,eAAe,CAAC,iDAAiD,CACvE,CAAC;IACD,OAAO,IAAI;EACb;EAEA,MAAMc,iBAAiB,GAAGZ,aAAa,CAAC,CAAC;EACzC,MAAMa,QAAQ,GAAGhB,QAAQ,CAACa,EAAuB;EACjD,MAAMI,eAAe,GAAGb,WAAW,CAAC,CAAC;EACrC,MAAMc,WAAW,GAAGX,cAAc,CAAC,CAAC;EACpC,MAAMY,OAAO,GAAGd,UAAU,CAAC,CAAC;EAE5B,IAAI,CAACU,iBAAiB,EAAE;IACtBL,OAAO,CAACI,OAAO,GAAG,IAAIb,eAAe,CAAC,2BAA2B,CAAC,CAAC;IACnE,OAAO,IAAI;EACb;EAEA,MAAMmB,eAAe,GAAGd,kBAAkB,CAAC,CAAC;EAE5C,OAAOJ,eAAe,CAAC;IACrBmB,MAAM,EAAEX,OAAO,CAACW,MAAM;IACtBC,MAAM,EAAE;MACNC,QAAQ,EAAEN,eAAe;MACzBO,UAAU,EAAET,iBAAiB;MAC7BC,QAAQ;MACRE,WAAW;MACXC,OAAO;MACPC;IACF,CAAC;IACDK,cAAc,EAAEf,OAAO,CAACe,cAAc;IACtCX,OAAO,EAAEJ,OAAO,CAACI,OAAO;IACxBY,cAAc,EAAEhB,OAAO,CAACgB;EAC1B,CAAC,CAAC,CAACC,IAAI,CAAEC,UAAU,IAAK;IACtB,IAAI,CAACA,UAAU,EAAE;MACf,OAAO,IAAI;IACb;IAEA,OAAO;MACL,GAAGA,UAAU;MACbpB,YAAY,EAAE,MAAAA,CAAA,KAAY;QACxB,OAAOA,YAAY,CAAC;UAClBe,QAAQ,EAAEK,UAAU,CAACC,EAAE;UACvBC,OAAO,EAAEF,UAAU,CAACE,OAAO;UAC3BC,QAAQ,EAAEH,UAAU,
|
|
1
|
+
{"version":3,"names":["Platform","HotUpdaterError","fetchUpdateInfo","getAppVersion","getBundleId","getChannel","getFingerprintHash","getMinBundleId","updateBundle","checkForUpdate","options","__DEV__","includes","OS","onError","currentAppVersion","platform","currentBundleId","minBundleId","channel","fingerprintHash","source","params","bundleId","appVersion","requestHeaders","requestTimeout","then","updateInfo","id","fileUrl","fileHash","status","getUpdateSource","baseUrl","updateStrategy"],"sourceRoot":"../../src","sources":["checkForUpdate.ts"],"mappings":";;AACA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,eAAe,QAAQ,YAAS;AACzC,SAASC,eAAe,QAA2B,sBAAmB;AACtE,SACEC,aAAa,EACbC,WAAW,EACXC,UAAU,EACVC,kBAAkB,EAClBC,cAAc,EACdC,YAAY,QACP,aAAU;AAqBjB,OAAO,eAAeC,cAAcA,CAClCC,OAA8B,EACQ;EACtC,IAAIC,OAAO,EAAE;IACX,OAAO,IAAI;EACb;EAEA,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAACC,QAAQ,CAACZ,QAAQ,CAACa,EAAE,CAAC,EAAE;IAC7CH,OAAO,CAACI,OAAO,GACb,IAAIb,eAAe,CAAC,iDAAiD,CACvE,CAAC;IACD,OAAO,IAAI;EACb;EAEA,MAAMc,iBAAiB,GAAGZ,aAAa,CAAC,CAAC;EACzC,MAAMa,QAAQ,GAAGhB,QAAQ,CAACa,EAAuB;EACjD,MAAMI,eAAe,GAAGb,WAAW,CAAC,CAAC;EACrC,MAAMc,WAAW,GAAGX,cAAc,CAAC,CAAC;EACpC,MAAMY,OAAO,GAAGd,UAAU,CAAC,CAAC;EAE5B,IAAI,CAACU,iBAAiB,EAAE;IACtBL,OAAO,CAACI,OAAO,GAAG,IAAIb,eAAe,CAAC,2BAA2B,CAAC,CAAC;IACnE,OAAO,IAAI;EACb;EAEA,MAAMmB,eAAe,GAAGd,kBAAkB,CAAC,CAAC;EAE5C,OAAOJ,eAAe,CAAC;IACrBmB,MAAM,EAAEX,OAAO,CAACW,MAAM;IACtBC,MAAM,EAAE;MACNC,QAAQ,EAAEN,eAAe;MACzBO,UAAU,EAAET,iBAAiB;MAC7BC,QAAQ;MACRE,WAAW;MACXC,OAAO;MACPC;IACF,CAAC;IACDK,cAAc,EAAEf,OAAO,CAACe,cAAc;IACtCX,OAAO,EAAEJ,OAAO,CAACI,OAAO;IACxBY,cAAc,EAAEhB,OAAO,CAACgB;EAC1B,CAAC,CAAC,CAACC,IAAI,CAAEC,UAAU,IAAK;IACtB,IAAI,CAACA,UAAU,EAAE;MACf,OAAO,IAAI;IACb;IAEA,OAAO;MACL,GAAGA,UAAU;MACbpB,YAAY,EAAE,MAAAA,CAAA,KAAY;QACxB,OAAOA,YAAY,CAAC;UAClBe,QAAQ,EAAEK,UAAU,CAACC,EAAE;UACvBC,OAAO,EAAEF,UAAU,CAACE,OAAO;UAC3BC,QAAQ,EAAEH,UAAU,CAACG,QAAQ;UAC7BC,MAAM,EAAEJ,UAAU,CAACI;QACrB,CAAC,CAAC;MACJ;IACF,CAAC;EACH,CAAC,CAAC;AACJ;AAYA,OAAO,MAAMC,eAAe,GAC1BA,CAACC,OAAe,EAAExB,OAA+B,KAChDY,MAA0B,IAAK;EAC9B,QAAQZ,OAAO,CAACyB,cAAc;IAC5B,KAAK,aAAa;MAAE;QAClB,IAAI,CAACb,MAAM,CAACF,eAAe,EAAE;UAC3B,MAAM,IAAInB,eAAe,CAAC,8BAA8B,CAAC;QAC3D;QACA,OAAO,GAAGiC,OAAO,gBAAgBZ,MAAM,CAACN,QAAQ,IAAIM,MAAM,CAACF,eAAe,IAAIE,MAAM,CAACH,OAAO,IAAIG,MAAM,CAACJ,WAAW,IAAII,MAAM,CAACC,QAAQ,EAAE;MACzI;IACA,KAAK,YAAY;MAAE;QACjB,OAAO,GAAGW,OAAO,gBAAgBZ,MAAM,CAACN,QAAQ,IAAIM,MAAM,CAACE,UAAU,IAAIF,MAAM,CAACH,OAAO,IAAIG,MAAM,CAACJ,WAAW,IAAII,MAAM,CAACC,QAAQ,EAAE;MACpI;IACA;MACE,OAAOW,OAAO;EAClB;AACF,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { runUpdateProcess } from "./runUpdateProcess.js";
|
|
|
6
6
|
import { hotUpdaterStore } from "./store.js";
|
|
7
7
|
import { wrap } from "./wrap.js";
|
|
8
8
|
export * from "./store.js";
|
|
9
|
+
export { extractSignatureFailure, isSignatureVerificationError } from "./types.js";
|
|
9
10
|
addListener("onProgress", ({
|
|
10
11
|
progress
|
|
11
12
|
}) => {
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["checkForUpdate","addListener","getAppVersion","getBundleId","getChannel","getFingerprintHash","getMinBundleId","reload","updateBundle","runUpdateProcess","hotUpdaterStore","wrap","progress","setState","HotUpdater","isUpdateDownloaded","getSnapshot","getUpdateSource"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,qBAAkB;AACjD,SACEC,WAAW,EACXC,aAAa,EACbC,WAAW,EACXC,UAAU,EACVC,kBAAkB,EAClBC,cAAc,EACdC,MAAM,EACNC,YAAY,QACP,aAAU;AACjB,SAASC,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,eAAe,QAAQ,YAAS;AACzC,SAASC,IAAI,QAAQ,WAAQ;AAG7B,cAAc,YAAS;
|
|
1
|
+
{"version":3,"names":["checkForUpdate","addListener","getAppVersion","getBundleId","getChannel","getFingerprintHash","getMinBundleId","reload","updateBundle","runUpdateProcess","hotUpdaterStore","wrap","extractSignatureFailure","isSignatureVerificationError","progress","setState","HotUpdater","isUpdateDownloaded","getSnapshot","getUpdateSource"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,qBAAkB;AACjD,SACEC,WAAW,EACXC,aAAa,EACbC,WAAW,EACXC,UAAU,EACVC,kBAAkB,EAClBC,cAAc,EACdC,MAAM,EACNC,YAAY,QACP,aAAU;AACjB,SAASC,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,eAAe,QAAQ,YAAS;AACzC,SAASC,IAAI,QAAQ,WAAQ;AAG7B,cAAc,YAAS;AACvB,SACEC,uBAAuB,EACvBC,4BAA4B,QAEvB,YAAS;AAGhBZ,WAAW,CAAC,YAAY,EAAE,CAAC;EAAEa;AAAS,CAAC,KAAK;EAC1CJ,eAAe,CAACK,QAAQ,CAAC;IACvBD;EACF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,MAAME,UAAU,GAAG;EACxB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEL,IAAI;EACJ;AACF;AACA;EACEJ,MAAM;EACN;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEU,kBAAkB,EAAEA,CAAA,KAAMP,eAAe,CAACQ,WAAW,CAAC,CAAC,CAACD,kBAAkB;EAC1E;AACF;AACA;EACEf,aAAa;EACb;AACF;AACA;EACEC,WAAW;EACX;AACF;AACA;EACEG,cAAc;EACd;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEF,UAAU;EACV;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEH,WAAW;EACX;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACED,cAAc;EACd;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACES,gBAAgB;EAChB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACED,YAAY;EACZ;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEH;AACF,CAAC;AAED,SAASc,eAAe,QAAQ,qBAAkB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../../src","sources":["specs/NativeHotUpdater.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../../src","sources":["specs/NativeHotUpdater.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAiClD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Information about a signature verification failure.
|
|
5
|
+
* This is a security-critical event that indicates the bundle
|
|
6
|
+
* may have been tampered with or the public key is misconfigured.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks if an error is a signature verification failure.
|
|
11
|
+
* Matches error messages from both iOS and Android native implementations.
|
|
12
|
+
*
|
|
13
|
+
* **IMPORTANT**: This function relies on specific error message patterns from native code.
|
|
14
|
+
* If you change the error messages in the native implementations, update these patterns:
|
|
15
|
+
* - iOS: `ios/HotUpdater/Internal/SignatureVerifier.swift` (SignatureVerificationError)
|
|
16
|
+
* - Android: `android/src/main/java/com/hotupdater/SignatureVerifier.kt` (SignatureVerificationException)
|
|
17
|
+
*/
|
|
18
|
+
export function isSignatureVerificationError(error) {
|
|
19
|
+
if (!(error instanceof Error)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const message = error.message.toLowerCase();
|
|
23
|
+
|
|
24
|
+
// Match iOS SignatureVerificationError messages
|
|
25
|
+
// Match Android SignatureVerificationException messages
|
|
26
|
+
return message.includes("signature verification") || message.includes("public key not configured") || message.includes("public key format is invalid") || message.includes("signature format is invalid") || message.includes("bundle may be corrupted or tampered");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extracts signature verification failure details from an error.
|
|
31
|
+
*/
|
|
32
|
+
export function extractSignatureFailure(error, bundleId) {
|
|
33
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
34
|
+
return {
|
|
35
|
+
bundleId,
|
|
36
|
+
message: normalizedError.message,
|
|
37
|
+
error: normalizedError
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["isSignatureVerificationError","error","Error","message","toLowerCase","includes","extractSignatureFailure","bundleId","normalizedError","String"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,4BAA4BA,CAACC,KAAc,EAAW;EACpE,IAAI,EAAEA,KAAK,YAAYC,KAAK,CAAC,EAAE;IAC7B,OAAO,KAAK;EACd;EAEA,MAAMC,OAAO,GAAGF,KAAK,CAACE,OAAO,CAACC,WAAW,CAAC,CAAC;;EAE3C;EACA;EACA,OACED,OAAO,CAACE,QAAQ,CAAC,wBAAwB,CAAC,IAC1CF,OAAO,CAACE,QAAQ,CAAC,2BAA2B,CAAC,IAC7CF,OAAO,CAACE,QAAQ,CAAC,8BAA8B,CAAC,IAChDF,OAAO,CAACE,QAAQ,CAAC,6BAA6B,CAAC,IAC/CF,OAAO,CAACE,QAAQ,CAAC,qCAAqC,CAAC;AAE3D;;AAEA;AACA;AACA;AACA,OAAO,SAASC,uBAAuBA,CACrCL,KAAc,EACdM,QAAgB,EACc;EAC9B,MAAMC,eAAe,GACnBP,KAAK,YAAYC,KAAK,GAAGD,KAAK,GAAG,IAAIC,KAAK,CAACO,MAAM,CAACR,KAAK,CAAC,CAAC;EAE3D,OAAO;IACLM,QAAQ;IACRJ,OAAO,EAAEK,eAAe,CAACL,OAAO;IAChCF,KAAK,EAAEO;EACT,CAAC;AACH","ignoreList":[]}
|
|
@@ -3,6 +3,7 @@ import { updateBundle } from "./native";
|
|
|
3
3
|
import { wrap } from "./wrap";
|
|
4
4
|
export type { HotUpdaterEvent } from "./native";
|
|
5
5
|
export * from "./store";
|
|
6
|
+
export { extractSignatureFailure, isSignatureVerificationError, type SignatureVerificationFailure, } from "./types";
|
|
6
7
|
export type { HotUpdaterOptions } from "./wrap";
|
|
7
8
|
export declare const HotUpdater: {
|
|
8
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAQL,YAAY,EACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,cAAc,SAAS,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAQhD,eAAO,MAAM,UAAU;IACrB;;;;;;;;;;;;;;;;;;;;;OAqBG;;IAEH;;OAEG;;IAEH;;;;;;;;;;;;;;;;OAgBG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;;;;;;;;;;OAYG;;IAEH;;;;;;;;;;;;;;;;OAgBG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;;IAEH;;;;;;;;;;OAUG;;CAEJ,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAQL,YAAY,EACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,cAAc,SAAS,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,4BAA4B,GAClC,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAQhD,eAAO,MAAM,UAAU;IACrB;;;;;;;;;;;;;;;;;;;;;OAqBG;;IAEH;;OAEG;;IAEH;;;;;;;;;;;;;;;;OAgBG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;;;;;;;;;;OAYG;;IAEH;;;;;;;;;;;;;;;;OAgBG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;;IAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;;IAEH;;;;;;;;;;OAUG;;CAEJ,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -3,8 +3,13 @@ export interface UpdateBundleParams {
|
|
|
3
3
|
bundleId: string;
|
|
4
4
|
fileUrl: string | null;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* File hash for integrity/signature verification.
|
|
7
|
+
*
|
|
8
|
+
* Format depends on signing configuration:
|
|
9
|
+
* - Signed: `sig:<base64_signature>` - Native will verify signature (and implicitly hash)
|
|
10
|
+
* - Unsigned: `<hex_hash>` - Native will verify SHA256 hash only
|
|
11
|
+
*
|
|
12
|
+
* Native determines verification mode by checking for "sig:" prefix.
|
|
8
13
|
*/
|
|
9
14
|
fileHash: string | null;
|
|
10
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeHotUpdater.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeHotUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB
|
|
1
|
+
{"version":3,"file":"NativeHotUpdater.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeHotUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IAEvC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAG3D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,CAAC;CACH;;AAED,wBAAoE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Information about a signature verification failure.
|
|
3
|
+
* This is a security-critical event that indicates the bundle
|
|
4
|
+
* may have been tampered with or the public key is misconfigured.
|
|
5
|
+
*/
|
|
6
|
+
export interface SignatureVerificationFailure {
|
|
7
|
+
/**
|
|
8
|
+
* The bundle ID that failed verification.
|
|
9
|
+
*/
|
|
10
|
+
bundleId: string;
|
|
11
|
+
/**
|
|
12
|
+
* Human-readable error message from the native layer.
|
|
13
|
+
*/
|
|
14
|
+
message: string;
|
|
15
|
+
/**
|
|
16
|
+
* The underlying error object.
|
|
17
|
+
*/
|
|
18
|
+
error: Error;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Checks if an error is a signature verification failure.
|
|
22
|
+
* Matches error messages from both iOS and Android native implementations.
|
|
23
|
+
*
|
|
24
|
+
* **IMPORTANT**: This function relies on specific error message patterns from native code.
|
|
25
|
+
* If you change the error messages in the native implementations, update these patterns:
|
|
26
|
+
* - iOS: `ios/HotUpdater/Internal/SignatureVerifier.swift` (SignatureVerificationError)
|
|
27
|
+
* - Android: `android/src/main/java/com/hotupdater/SignatureVerifier.kt` (SignatureVerificationException)
|
|
28
|
+
*/
|
|
29
|
+
export declare function isSignatureVerificationError(error: unknown): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Extracts signature verification failure details from an error.
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractSignatureFailure(error: unknown, bundleId: string): SignatureVerificationFailure;
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|