A new Apple iOS feature to "attest" an app is healthy.
https://developer.apple.com/documentation/devicecheck
DeviceCheck launched in the summer of 2020 as part of the iOS 14 release.
On paper, the Public Interface to the DCAppAttestService Class is tiny:
var shared: DCAppAttestService
var isSupported: Bool
func generateKey(completionHandler: (String?, Error?) -> Void)
func attestKey(String, clientDataHash: Data, completionHandler: (Data?, Error?) -> Void)
func generateAssertion(String, clientDataHash: Data, completionHandler: (Data?, Error?) -> Void)
But then it becomes apparent there is a sister class: dcdevice:
class var current: DCDevice
var isSupported: Bool
func generateToken(completionHandler: (Data?, Error?) -> Void)
To use the DCDevice class, the app ID must with this Capability on developer.apple.com.
-
Keygenerated by App Attest aregeneratedandpersistedinside the device’sSecurity Enclave. -
Like other
Secure Enclavework, the app is never given thePrivate Key. -
The app is responsible for persisting a
key Identifierso you can always point theSecure Enclaveto the correctPrivate Key. -
The app can get a serialized version of the
Public Key. But, before that happens, you callservice.attestKey. This makes a call toApple's attestation service. Apple servers generate anattestation objectand return it to the app. That object can then be passed to your server. -
This
attestationstep is purely anenrolmentstep to ensure the app'sApp Attest Public Keyresists tampering. -
Other parts of the
attestation objectadditional your server to detectreplay attacks.
-
The request to Apple's servers can fail. Or forced to fail.
-
if service.isSupportedreferences aYes/NoObjective-C property that could be swizzled at run-time.