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 签名令牌。不是我最喜欢的,但也支持这些设备有点实用。