Struct DCAppAttestService

Source
#[repr(C)]
pub struct DCAppAttestService { /* private fields */ }
Available on crate feature DCAppAttestService only.
Expand description

A service that you use to validate the instance of your app running on a device.

Use the DeviceCheck/DCAppAttestService/sharedService instance of the DeviceCheck/DCAppAttestService class to assert the legitimacy of a particular instance of your app to your server. After ensuring service availability by reading the DeviceCheck/DCAppAttestService/supported property, you use the service to:

  • Create a cryptographic key in the Secure Enclave by calling the DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method.
  • Ask Apple to certify the key by calling the DeviceCheck/DCAppAttestService/attestKey:clientDataHash:completionHandler: method. - Prepare an assertion of your app’s integrity to accompany any or all server requests using the DeviceCheck/DCAppAttestService/generateAssertion:clientDataHash:completionHandler: method.

For more information about how to support App Attest in your app, see . For information about the complementary procedures you implement on your server, see .

  • Note: To use the App Attest service, your app must have an app ID that you register on the Apple Developer website.

See also Apple’s documentation

Implementations§

Source§

impl DCAppAttestService

Source

pub unsafe fn sharedService() -> Retained<DCAppAttestService>

The shared App Attest service that you use to validate your app.

Use the shared instance of the service to generate and to certify a cryptographic key, and then to assert your app’s validity using that key.

Source

pub unsafe fn isSupported(&self) -> bool

A Boolean value that indicates whether a particular device provides the App Attest service.

Important: Not all device types support the App Attest service, so check for support before using the service.

If you read DeviceCheck/DCAppAttestService/supported from an app running on a Mac device, the value is

<doc ://com.apple.documentation/documentation/swift/false>. This includes

Mac Catalyst apps, and iOS or iPadOS apps running on Apple silicon.

If you read DeviceCheck/DCAppAttestService/supported from within an app extension, the value might be <doc ://com.apple.documentation/documentation/swift/true> or <doc ://com.apple.documentation/documentation/swift/false>, depending on the extension type. However, most extensions don’t support App Attest. The DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method fails when you call it from an app extension, regardless of the value of DeviceCheck/DCAppAttestService/supported.

The only app extensions that support App Attest are watchOS extensions in watchOS 9 or later. For these extensions, you can use the results from DeviceCheck/DCAppAttestService/supported to indicate whether your WatchKit extension bypasses attestation.

Source

pub unsafe fn generateKeyWithCompletionHandler( &self, completion_handler: &Block<dyn Fn(*mut NSString, *mut NSError)>, )

Available on crate feature block2 only.

Creates a new cryptographic key for use with the App Attest service.

Concurrency Note: You can call this method from synchronous code using a completion handler, as shown on this page, or you can call it as an asynchronous method that has the following declaration:

func generateKey() async throws -> String

For example:

let keyIdentifier = try await generateKey()

For information about concurrency and asynchronous code in Swift, see <doc ://com.apple.documentation/documentation/swift/calling-objective-c-apis-asynchronously>.

Call this method to request the creation of a secure, unattested key pair on a device for a specific user. On success, the method provides your app with an identifier that represents the key pair stored in the Secure Enclave. Because there’s no way to use or retrieve the key without the identifier, you’ll want to either record it in your app or on your server right away. If key generation fails, the closure provides a DeviceCheck/DCError-swift.struct that indicates the reason for the failure.

Create a unique key for each user account on a device. Otherwise it’s hard to detect an attack that uses a single compromised device to serve multiple remote users running a compromised version of your app. For more information, see .

After you get the identifier, you call the DeviceCheck/DCAppAttestService/attestKey:clientDataHash:completionHandler: method with the key identifier to ask Apple to attest to the validity of the associated key. Later, you call the DeviceCheck/DCAppAttestService/generateAssertion:clientDataHash:completionHandler: method with the key identifier to answer a challenge from your server, and establish the legitimacy of this instance of your app.

  • Parameters:
  • completionHandler: A closure that the method calls upon completion with the following parameters:
  • keyId: An identifier that you use to refer to the key. The framework securely stores the key in the Secure Enclave.
  • error: A DeviceCheck/DCError-swift.struct instance that indicates the reason for failure, or nil on success.
Source

pub unsafe fn attestKey_clientDataHash_completionHandler( &self, key_id: &NSString, client_data_hash: &NSData, completion_handler: &Block<dyn Fn(*mut NSData, *mut NSError)>, )

Available on crate feature block2 only.

Asks Apple to attest to the validity of a generated cryptographic key.

Concurrency Note: You can call this method from synchronous code using a completion handler, as shown on this page, or you can call it as an asynchronous method that has the following declaration:

func attestKey(_ keyId: String, clientDataHash: Data) async throws -> Data

For information about concurrency and asynchronous code in Swift, see <doc ://com.apple.documentation/documentation/swift/calling-objective-c-apis-asynchronously>.

This method asks Apple to attest to the validity of a key that you previously generated with a call to the DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method. Provide the method with both the key identifier and a computed hash of a data block that includes a one-time challenge from your server to prevent replay attacks. For example, you can use CryptoKit to create a <doc ://com.apple.documentation/documentation/cryptokit/sha256> hash of challenge data:

import CryptoKit let hash = Data(SHA256.hash(data: challenge)) // A
challenge from your server.

The attest method calls its completion handler to return an attestation object to you, which you must send to your server for verification. A compromised version of your app could falsify the verification result, thus circumventing App Attest.

If you successfully verify the attestation object on your server, as described in , then you can associate the key identifier with the user on the device for future reference. You’ll need the identifier to generate assertions with calls to DeviceCheck/DCAppAttestService/generateAssertion:clientDataHash:completionHandler:. If your server fails to verify the attestation object, discard the key identifier.

If the method’s completion handler returns the DeviceCheck/DCError-swift.struct/serverUnavailable error — typically due to network connectivity issues — it means that the framework failed to reach the App Attest service to complete the attestation. In this case, retry attestation again using the same key and client data hash later to avoid unnecessarily generating new keys. Retrying with the same inputs helps to preserve the risk metric for a given device.

  • Parameters:
  • keyId: The identifier you received when generating a cryptographic key by calling the DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method.
  • clientDataHash: A SHA256 hash of a unique, single-use data block that embeds a challenge from your server. Should be at least 16 bytes in length.
  • completionHandler: A closure that the method calls upon completion with the following parameters:
  • attestationObject: A statement from Apple about the validity of the key associated with keyId. Send this to your server for processing.
  • error: A DeviceCheck/DCError-swift.struct instance that indicates the reason for failure, or nil on success.
Source

pub unsafe fn generateAssertion_clientDataHash_completionHandler( &self, key_id: &NSString, client_data_hash: &NSData, completion_handler: &Block<dyn Fn(*mut NSData, *mut NSError)>, )

Available on crate feature block2 only.

Creates a block of data that demonstrates the legitimacy of an instance of your app running on a device.

Concurrency Note: You can call this method from synchronous code using a completion handler, as shown on this page, or you can call it as an asynchronous method that has the following declaration:

func generateAssertion(_ keyId: String, clientDataHash: Data) async throws -> Data

For information about concurrency and asynchronous code in Swift, see <doc ://com.apple.documentation/documentation/swift/calling-objective-c-apis-asynchronously>.

After generating a key with the DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method and validating it with the DeviceCheck/DCAppAttestService/attestKey:clientDataHash:completionHandler: method, you can use the key at critical moments in your app’s life cycle — like when a user tries to access premium content — to reaffirm the legitimacy of a given instance of your app. Do this by using the DeviceCheck/DCAppAttestService/generateAssertion:clientDataHash:completionHandler: method to sign server requests with your attested key.

You provide the key identifier and a hash of the request that includes a challenge from your server to prevent replay attacks, where an attacker reuses captured network traffic to pose as someone else. The method returns an assertion object in its completion handler that you send to your server for verification, as described in .

  • Parameters:
  • keyId: The identifier you received when generating a cryptographic key by calling the DeviceCheck/DCAppAttestService/generateKeyWithCompletionHandler: method.
  • clientDataHash: A SHA256 hash of a unique, single-use data block that represents the client data to be signed with the attested private key. Should be at least 16 bytes in length.
  • completionHandler: A closure that the method calls upon completion with the following parameters:
  • assertionObject: A data structure that you send to your server for processing.
  • error : A DeviceCheck/DCError-swift.struct instance that indicates the reason for failure, or nil on success.
Source§

impl DCAppAttestService

Methods declared on superclass NSObject.

Source

pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>

Source

pub unsafe fn new() -> Retained<Self>

Methods from Deref<Target = NSObject>§

Source

pub fn doesNotRecognizeSelector(&self, sel: Sel) -> !

Handle messages the object doesn’t recognize.

See Apple’s documentation for details.

Methods from Deref<Target = AnyObject>§

Source

pub fn class(&self) -> &'static AnyClass

Dynamically find the class of this object.

§Example

Check that an instance of NSObject has the precise class NSObject.

use objc2::ClassType;
use objc2::runtime::NSObject;

let obj = NSObject::new();
assert_eq!(obj.class(), NSObject::class());
Source

pub unsafe fn get_ivar<T>(&self, name: &str) -> &T
where T: Encode,

👎Deprecated: this is difficult to use correctly, use Ivar::load instead.

Use Ivar::load instead.

§Safety

The object must have an instance variable with the given name, and it must be of type T.

See Ivar::load_ptr for details surrounding this.

Source

pub fn downcast_ref<T>(&self) -> Option<&T>
where T: DowncastTarget,

Attempt to downcast the object to a class of type T.

This is the reference-variant. Use Retained::downcast if you want to convert a retained object to another type.

§Mutable classes

Some classes have immutable and mutable variants, such as NSString and NSMutableString.

When some Objective-C API signature says it gives you an immutable class, it generally expects you to not mutate that, even though it may technically be mutable “under the hood”.

So using this method to convert a NSString to a NSMutableString, while not unsound, is generally frowned upon unless you created the string yourself, or the API explicitly documents the string to be mutable.

See Apple’s documentation on mutability and on isKindOfClass: for more details.

§Generic classes

Objective-C generics are called “lightweight generics”, and that’s because they aren’t exposed in the runtime. This makes it impossible to safely downcast to generic collections, so this is disallowed by this method.

You can, however, safely downcast to generic collections where all the type-parameters are AnyObject.

§Panics

This works internally by calling isKindOfClass:. That means that the object must have the instance method of that name, and an exception will be thrown (if CoreFoundation is linked) or the process will abort if that is not the case. In the vast majority of cases, you don’t need to worry about this, since both root objects NSObject and NSProxy implement this method.

§Examples

Cast an NSString back and forth from NSObject.

use objc2::rc::Retained;
use objc2_foundation::{NSObject, NSString};

let obj: Retained<NSObject> = NSString::new().into_super();
let string = obj.downcast_ref::<NSString>().unwrap();
// Or with `downcast`, if we do not need the object afterwards
let string = obj.downcast::<NSString>().unwrap();

Try (and fail) to cast an NSObject to an NSString.

use objc2_foundation::{NSObject, NSString};

let obj = NSObject::new();
assert!(obj.downcast_ref::<NSString>().is_none());

Try to cast to an array of strings.

use objc2_foundation::{NSArray, NSObject, NSString};

let arr = NSArray::from_retained_slice(&[NSObject::new()]);
// This is invalid and doesn't type check.
let arr = arr.downcast_ref::<NSArray<NSString>>();

This fails to compile, since it would require enumerating over the array to ensure that each element is of the desired type, which is a performance pitfall.

Downcast when processing each element instead.

use objc2_foundation::{NSArray, NSObject, NSString};

let arr = NSArray::from_retained_slice(&[NSObject::new()]);

for elem in arr {
    if let Some(data) = elem.downcast_ref::<NSString>() {
        // handle `data`
    }
}

Trait Implementations§

Source§

impl AsRef<AnyObject> for DCAppAttestService

Source§

fn as_ref(&self) -> &AnyObject

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<DCAppAttestService> for DCAppAttestService

Source§

fn as_ref(&self) -> &Self

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<NSObject> for DCAppAttestService

Source§

fn as_ref(&self) -> &NSObject

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Borrow<AnyObject> for DCAppAttestService

Source§

fn borrow(&self) -> &AnyObject

Immutably borrows from an owned value. Read more
Source§

impl Borrow<NSObject> for DCAppAttestService

Source§

fn borrow(&self) -> &NSObject

Immutably borrows from an owned value. Read more
Source§

impl ClassType for DCAppAttestService

Source§

const NAME: &'static str = "DCAppAttestService"

The name of the Objective-C class that this type represents. Read more
Source§

type Super = NSObject

The superclass of this class. Read more
Source§

type ThreadKind = <<DCAppAttestService as ClassType>::Super as ClassType>::ThreadKind

Whether the type can be used from any thread, or from only the main thread. Read more
Source§

fn class() -> &'static AnyClass

Get a reference to the Objective-C class that this type represents. Read more
Source§

fn as_super(&self) -> &Self::Super

Get an immutable reference to the superclass.
Source§

impl Debug for DCAppAttestService

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Deref for DCAppAttestService

Source§

type Target = NSObject

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl Hash for DCAppAttestService

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Message for DCAppAttestService

Source§

fn retain(&self) -> Retained<Self>
where Self: Sized,

Increment the reference count of the receiver. Read more
Source§

impl NSObjectProtocol for DCAppAttestService

Source§

fn isEqual(&self, other: Option<&AnyObject>) -> bool
where Self: Sized + Message,

Check whether the object is equal to an arbitrary other object. Read more
Source§

fn hash(&self) -> usize
where Self: Sized + Message,

An integer that can be used as a table address in a hash table structure. Read more
Source§

fn isKindOfClass(&self, cls: &AnyClass) -> bool
where Self: Sized + Message,

Check if the object is an instance of the class, or one of its subclasses. Read more
Source§

fn is_kind_of<T>(&self) -> bool
where T: ClassType, Self: Sized + Message,

👎Deprecated: use isKindOfClass directly, or cast your objects with AnyObject::downcast_ref
Check if the object is an instance of the class type, or one of its subclasses. Read more
Source§

fn isMemberOfClass(&self, cls: &AnyClass) -> bool
where Self: Sized + Message,

Check if the object is an instance of a specific class, without checking subclasses. Read more
Source§

fn respondsToSelector(&self, aSelector: Sel) -> bool
where Self: Sized + Message,

Check whether the object implements or inherits a method with the given selector. Read more
Source§

fn conformsToProtocol(&self, aProtocol: &AnyProtocol) -> bool
where Self: Sized + Message,

Check whether the object conforms to a given protocol. Read more
Source§

fn description(&self) -> Retained<NSObject>
where Self: Sized + Message,

A textual representation of the object. Read more
Source§

fn debugDescription(&self) -> Retained<NSObject>
where Self: Sized + Message,

A textual representation of the object to use when debugging. Read more
Source§

fn isProxy(&self) -> bool
where Self: Sized + Message,

Check whether the receiver is a subclass of the NSProxy root class instead of the usual NSObject. Read more
Source§

fn retainCount(&self) -> usize
where Self: Sized + Message,

The reference count of the object. Read more
Source§

impl PartialEq for DCAppAttestService

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl RefEncode for DCAppAttestService

Source§

const ENCODING_REF: Encoding = <NSObject as ::objc2::RefEncode>::ENCODING_REF

The Objective-C type-encoding for a reference of this type. Read more
Source§

impl DowncastTarget for DCAppAttestService

Source§

impl Eq for DCAppAttestService

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<'a, T> AllocAnyThread for T
where T: ClassType<ThreadKind = dyn AllocAnyThread + 'a> + ?Sized,

Source§

fn alloc() -> Allocated<Self>
where Self: Sized + ClassType,

Allocate a new instance of the class. Read more
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,