SwiftJWT 在 JWT.init() 调用时使 iOS 应用程序崩溃
SwiftJWT crashes iOS App on JWT.init() call
仅当从 AppStore 分布式可执行文件执行时,以下代码才会在 iPad mini 2 / 3 上崩溃。
let jwtVerifier = JWTVerifier.es512(publicKey: publicKey.data(using: .utf8)!)
do {
let parsedJwt = try JWT<LicenseJWTClaims>(jwtString: jwt, verifier: jwtVerifier) // <== crashes here
return License(jwt: parsedJwt, raw_jwt_string: jwt)
} catch {
}
// LicenseJWTClaims for reference
internal struct LicenseJWTClaims: Claims {
let exp: Date?
let nbf: Date?
let iat: Date?
let licenseKey: String?
}
当通过 XCode 安装时,代码在每台设备上都能正常工作。当从 App Store 安装时,该应用程序也适用于 'normal'(非迷你)iPads。
您将如何继续分析这个问题?您甚至有可用的修复程序吗?
在下面找到崩溃日志的相关部分:
Thread 0 name: Dispatch queue: com.apple.avfoundation.metadataoutput.objectqueue
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001b1b33b00 specialized _fatalErrorMessage+ 2112256 (_:_:file:line:flags:) + 296
1 libswiftCore.dylib 0x00000001b1b33b00 specialized _fatalErrorMessage+ 2112256 (_:_:file:line:flags:) + 296
2 libswiftCore.dylib 0x00000001b1b65300 specialized _NativeDictionary.bridged+ 2315008 () + 288
3 libswiftCore.dylib 0x00000001b19b1f70 _NativeDictionary.bridged+ 532336 () + 20
4 CryptorECC 0x0000000100564958 specialized ECPublicKey.init(der:) + 51544 (ECPublicKey.swift:144)
5 CryptorECC 0x0000000100564240 ECPublicKey.__allocating_init(key:) + 49728 (ECPublicKey.swift:93)
6 SwiftJWT 0x00000001008a36d0 BlueECVerifier.verify(signature:for:) + 30416 (BlueECDSA.swift:99)
7 SwiftJWT 0x00000001008a34a8 BlueECVerifier.verify(jwt:) + 29864 (BlueECDSA.swift:84)
8 SwiftJWT 0x00000001008a3884 protocol witness for VerifierAlgorithm.verify(jwt:) in conformance BlueECVerifier + 30852 (<compiler-generated>:0)
9 SwiftJWT 0x00000001008b3200 JWT.init(jwtString:verifier:) + 94720 (JWT.swift:73)
10 Eliah 0x00000001004d25e4 LicenseValidator.constructLicense(with:) + 255460 (License.swift:64)
11 Eliah 0x00000001004d3eb4 LicenseViewController.licenseScanned(_:) + 261812 (LicenseViewController.swift:35)
12 Eliah 0x00000001004d518c partial apply for implicit closure #2 in implicit closure #1 in LicenseViewController.loadView() + 266636 (<compiler-generated>:0)
13 Eliah 0x00000001004d6c9c specialized LicenseScanView.metadataOutput(_:didOutput:from:) + 273564 (LicenseScanView.swift:0)
14 Eliah 0x00000001004d616c @objc LicenseScanView.metadataOutput(_:didOutput:from:) + 270700 (<compiler-generated>:0)
15 AVFoundation 0x000000018a40ac2c -[AVCaptureMetadataOutput _processSampleBuffer:] + 1284
16 AVFoundation 0x000000018a40a520 __46-[AVCaptureMetadataOutput _updateRemoteQueue:]_block_invoke + 100
17 CoreMedia 0x00000001878c9118 __FigRemoteOperationReceiverCreateMessageReceiver_block_invoke + 280
18 CoreMedia 0x00000001878e6718 __FigRemoteQueueReceiverSetHandler_block_invoke.2 + 224
19 libdispatch.dylib 0x0000000183d9c7d4 _dispatch_client_callout + 16
20 libdispatch.dylib 0x0000000183d4101c _dispatch_continuation_pop$VARIANT$mp + 412
21 libdispatch.dylib 0x0000000183d50fa8 _dispatch_source_invoke$VARIANT$mp + 1308
22 libdispatch.dylib 0x0000000183d451f0 _dispatch_lane_serial_drain$VARIANT$mp + 284
23 libdispatch.dylib 0x0000000183d45e74 _dispatch_lane_invoke$VARIANT$mp + 480
24 libdispatch.dylib 0x0000000183d49eec _dispatch_main_queue_callback_4CF$VARIANT$mp + 784
25 CoreFoundation 0x00000001842efb20 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
26 CoreFoundation 0x00000001842eaa58 __CFRunLoopRun + 1924
27 CoreFoundation 0x00000001842e9fb4 CFRunLoopRunSpecific + 436
28 GraphicsServices 0x00000001864eb79c GSEventRunModal + 104
29 UIKitCore 0x00000001b07efc38 UIApplicationMain + 212
30 Eliah 0x0000000100499b88 main + 23432 (AppDelegate.swift:5)
31 libdyld.dylib 0x0000000183dad8e0 start + 4
这些都是限制为 iOS 12 的旧设备。目前尚不清楚您是否能够在其他 iOS 12 设备上使用它,但我会看看常见的OS 版本和架构的线程,看看你是否能发现一个模式。
从逻辑上讲,因为它只是通过应用程序商店上的发行版发生,要么是苹果方面的问题,不太可能修复,因为这些设备太旧了,要么是你将二进制文件发布到的方式应用商店。从逻辑上讲,摆弄 xcode 中的存档选项是值得一试的。
我想如果是我,我会考虑放弃对这些设备的支持并继续前进,因为 81% 的设备是 运行 iOS 14。(但我不能代表你情况)。
无论如何,祝你好运。这是一个棘手的问题。
CryptorEEC 是开源的。对不是系统框架的堆栈的最后调用是 ECPublicKey.swift:144.
正如您从 link 中看到的那样,它正在创建一个具有此值 kSecAttrKeyTypeECSECPrimeRandom
的字典。根据堆栈中的下一个调用,这是导致崩溃的原因。
我在 Google 上搜索了 kSecAttrKeyTypeECSECPrimeRandom
,我找到了这个 question on SO。
This answer 表明大于 256 的密钥对于 ECSEC 来说太大了。
这是一个有旧答案的老问题,这让我相信它会在具有旧 iOS 版本的旧设备上崩溃,因为在 iOS 13 或更高版本中引入了对更大键的支持,或者在带有 Secure Enclave 的设备中(我不确定)。
因为我不知道你是如何使用这个加密令牌的,所以我不能就如何解决这个问题提出建议,但我希望它至少有足够的信息让你做出决定。
虽然none个答案确实解决了问题,但我还是想分享调试方法和最终解决方案。
正在分析这个问题
开发版本没有产生错误。 JWT 令牌可以很好地解析。为了分析这个问题,我能够创建一个 Ad Hoc 分发并通过静态 Web 服务器分发它。
以这种方式安装,出现了与 App Store 构建相同的问题。
顺便说一下:'Rebuild from Bitcode' 与否无关紧要。
我的解决方案
...只是切换到 RSA 签名令牌。不是我最喜欢的,但也支持这些设备有点实用。
仅当从 AppStore 分布式可执行文件执行时,以下代码才会在 iPad mini 2 / 3 上崩溃。
let jwtVerifier = JWTVerifier.es512(publicKey: publicKey.data(using: .utf8)!)
do {
let parsedJwt = try JWT<LicenseJWTClaims>(jwtString: jwt, verifier: jwtVerifier) // <== crashes here
return License(jwt: parsedJwt, raw_jwt_string: jwt)
} catch {
}
// LicenseJWTClaims for reference
internal struct LicenseJWTClaims: Claims {
let exp: Date?
let nbf: Date?
let iat: Date?
let licenseKey: String?
}
当通过 XCode 安装时,代码在每台设备上都能正常工作。当从 App Store 安装时,该应用程序也适用于 'normal'(非迷你)iPads。
您将如何继续分析这个问题?您甚至有可用的修复程序吗?
在下面找到崩溃日志的相关部分:
Thread 0 name: Dispatch queue: com.apple.avfoundation.metadataoutput.objectqueue
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001b1b33b00 specialized _fatalErrorMessage+ 2112256 (_:_:file:line:flags:) + 296
1 libswiftCore.dylib 0x00000001b1b33b00 specialized _fatalErrorMessage+ 2112256 (_:_:file:line:flags:) + 296
2 libswiftCore.dylib 0x00000001b1b65300 specialized _NativeDictionary.bridged+ 2315008 () + 288
3 libswiftCore.dylib 0x00000001b19b1f70 _NativeDictionary.bridged+ 532336 () + 20
4 CryptorECC 0x0000000100564958 specialized ECPublicKey.init(der:) + 51544 (ECPublicKey.swift:144)
5 CryptorECC 0x0000000100564240 ECPublicKey.__allocating_init(key:) + 49728 (ECPublicKey.swift:93)
6 SwiftJWT 0x00000001008a36d0 BlueECVerifier.verify(signature:for:) + 30416 (BlueECDSA.swift:99)
7 SwiftJWT 0x00000001008a34a8 BlueECVerifier.verify(jwt:) + 29864 (BlueECDSA.swift:84)
8 SwiftJWT 0x00000001008a3884 protocol witness for VerifierAlgorithm.verify(jwt:) in conformance BlueECVerifier + 30852 (<compiler-generated>:0)
9 SwiftJWT 0x00000001008b3200 JWT.init(jwtString:verifier:) + 94720 (JWT.swift:73)
10 Eliah 0x00000001004d25e4 LicenseValidator.constructLicense(with:) + 255460 (License.swift:64)
11 Eliah 0x00000001004d3eb4 LicenseViewController.licenseScanned(_:) + 261812 (LicenseViewController.swift:35)
12 Eliah 0x00000001004d518c partial apply for implicit closure #2 in implicit closure #1 in LicenseViewController.loadView() + 266636 (<compiler-generated>:0)
13 Eliah 0x00000001004d6c9c specialized LicenseScanView.metadataOutput(_:didOutput:from:) + 273564 (LicenseScanView.swift:0)
14 Eliah 0x00000001004d616c @objc LicenseScanView.metadataOutput(_:didOutput:from:) + 270700 (<compiler-generated>:0)
15 AVFoundation 0x000000018a40ac2c -[AVCaptureMetadataOutput _processSampleBuffer:] + 1284
16 AVFoundation 0x000000018a40a520 __46-[AVCaptureMetadataOutput _updateRemoteQueue:]_block_invoke + 100
17 CoreMedia 0x00000001878c9118 __FigRemoteOperationReceiverCreateMessageReceiver_block_invoke + 280
18 CoreMedia 0x00000001878e6718 __FigRemoteQueueReceiverSetHandler_block_invoke.2 + 224
19 libdispatch.dylib 0x0000000183d9c7d4 _dispatch_client_callout + 16
20 libdispatch.dylib 0x0000000183d4101c _dispatch_continuation_pop$VARIANT$mp + 412
21 libdispatch.dylib 0x0000000183d50fa8 _dispatch_source_invoke$VARIANT$mp + 1308
22 libdispatch.dylib 0x0000000183d451f0 _dispatch_lane_serial_drain$VARIANT$mp + 284
23 libdispatch.dylib 0x0000000183d45e74 _dispatch_lane_invoke$VARIANT$mp + 480
24 libdispatch.dylib 0x0000000183d49eec _dispatch_main_queue_callback_4CF$VARIANT$mp + 784
25 CoreFoundation 0x00000001842efb20 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
26 CoreFoundation 0x00000001842eaa58 __CFRunLoopRun + 1924
27 CoreFoundation 0x00000001842e9fb4 CFRunLoopRunSpecific + 436
28 GraphicsServices 0x00000001864eb79c GSEventRunModal + 104
29 UIKitCore 0x00000001b07efc38 UIApplicationMain + 212
30 Eliah 0x0000000100499b88 main + 23432 (AppDelegate.swift:5)
31 libdyld.dylib 0x0000000183dad8e0 start + 4
这些都是限制为 iOS 12 的旧设备。目前尚不清楚您是否能够在其他 iOS 12 设备上使用它,但我会看看常见的OS 版本和架构的线程,看看你是否能发现一个模式。
从逻辑上讲,因为它只是通过应用程序商店上的发行版发生,要么是苹果方面的问题,不太可能修复,因为这些设备太旧了,要么是你将二进制文件发布到的方式应用商店。从逻辑上讲,摆弄 xcode 中的存档选项是值得一试的。
我想如果是我,我会考虑放弃对这些设备的支持并继续前进,因为 81% 的设备是 运行 iOS 14。(但我不能代表你情况)。
无论如何,祝你好运。这是一个棘手的问题。
CryptorEEC 是开源的。对不是系统框架的堆栈的最后调用是 ECPublicKey.swift:144.
正如您从 link 中看到的那样,它正在创建一个具有此值 kSecAttrKeyTypeECSECPrimeRandom
的字典。根据堆栈中的下一个调用,这是导致崩溃的原因。
我在 Google 上搜索了 kSecAttrKeyTypeECSECPrimeRandom
,我找到了这个 question on SO。
This answer 表明大于 256 的密钥对于 ECSEC 来说太大了。
这是一个有旧答案的老问题,这让我相信它会在具有旧 iOS 版本的旧设备上崩溃,因为在 iOS 13 或更高版本中引入了对更大键的支持,或者在带有 Secure Enclave 的设备中(我不确定)。
因为我不知道你是如何使用这个加密令牌的,所以我不能就如何解决这个问题提出建议,但我希望它至少有足够的信息让你做出决定。
虽然none个答案确实解决了问题,但我还是想分享调试方法和最终解决方案。
正在分析这个问题
开发版本没有产生错误。 JWT 令牌可以很好地解析。为了分析这个问题,我能够创建一个 Ad Hoc 分发并通过静态 Web 服务器分发它。
以这种方式安装,出现了与 App Store 构建相同的问题。
顺便说一下:'Rebuild from Bitcode' 与否无关紧要。
我的解决方案
...只是切换到 RSA 签名令牌。不是我最喜欢的,但也支持这些设备有点实用。