Perform cryptographic operations using Apple's Secure Enclave and App Attestation with React Native.
Important Note: App attestation service in iOS and Hardware-backed key generation in Android does not work on emulators, you will need to connect a real device.
- Hardware-backed key generation using Secure Enclave
- App Attestation with Apple's DeviceCheck framework
- Play Store Attestation with Google's Play Integrity API
- Secure asymmetric signing operations
- Verify app integrity for secure server communication
- iOS 14.0 or newer
- Devices with Secure Enclave (iPhone 5s or newer)
- React Native 0.75.0 or newer
npm install react-native-secure-enclave-operations react-native-nitro-modules
react-native-nitro-modules
is required as this library relies on Nitro Modules.
Platform | Support |
---|---|
iOS | âś… |
MacOS | âś… |
Android | âś… |
|-android/ (Kotlin implementation for Android)
|-ios/ (Swift implementation for iOS)
|-src/ (TypeScript definitions methods for NitroModules)
|-server/ (Sample Node.js implementation for server)
|-example/ (Sample React Native client side implementation)
|-src/
/**
* Check if App Attestation is supported on this device
* @returns Promise<boolean> - True if the device supports App Attestation
*/
function isAttestationSupportedIos(): Promise<boolean>;
/**
* Generate a new key pair in the Secure Enclave for App Attestation
* @returns Promise<string> - Key identifier for the generated key
*/
function generateKeyIos(): Promise<string>;
/**
* Attest a key with Apple's servers
* @param keyId - Key identifier from generateKey()
* @param challenge - Challenge from your server (should be unique per attestation)
* @returns Promise<string> - Base64-encoded attestation object to send to your server
*/
function attestKeyIos(keyId: string, challenge: string): Promise<string>;
/**
* Sign data with an attested key
* @param keyId - Key identifier from generateKey()
* @param data - Data to sign (usually your request payload)
* @returns Promise<string> - Base64-encoded assertion object to send to your server
*/
function generateAssertionIos(keyId: string, data: string): Promise<string>;
/**
* Check if Google Play Services is available on the device
* @returns Promise<boolean> - True if Google Play Services is available
*/
function isPlayServicesAvailableAndroid(): Promise<boolean>;
/**
* Prepare an integrity token for Google Play Integrity API
* @param cloudProjectNumber - Cloud project number from Google Cloud Console
* @returns Promise<boolean> - True if the integrity token was successfully prepared
*/
function prepareIntegrityTokenAndroid(cloudProjectNumber: string): Promise<boolean>;
/**
* @param requestHash - Hash of the request data to be signed
* @returns Promise<string> - Base64-encoded integrity token to send to your server
*/
export function requestIntegrityTokenAndroid(requestHash: string): Promise<string>;
/**
* @param challenge - Challenge from your server (should be unique per request)
* @param keyId - Key identifier from generateKey()
* @returns Promise<string> - Base64-encoded attestation object to send to your server
*/
export function getAttestationAndroid(challenge: string, keyId: string): Promise<string>
import {
isHardwareBackedKeyGenerationSupportedIos,
generateKeyIos,
attestKeyIos,
generateAssertionIos,
} from 'react-native-secure-enclave-operations';
// NOTE: The server functions are placeholders.
// Check the server/ directory for a sample implementation.
// Check if device supports hardware-backed key generation
const isSupported = await isHardwareBackedKeyGenerationSupportedIos();
if (!isSupported) {
console.warn('Device does not support hardware-backed key generation');
return;
}
// Generate a key pair
const keyId = await generateKeyIos();
console.log('Generated key ID:', keyId);
// Fetch a challenge from your server
const challenge = await fetchChallengeFromServer();
// Attest the key with Apple's servers
const attestationObject = await attestKeyIos(keyId, challenge);
// Send attestationObject to your server for verification
await verifyAttestationWithServer(attestationObject, challenge, keyId);
// Get another unique challenge from your server
const anotherChallenge = await fetchChallengeFromServer();
// Use the key to sign data
const message = 'data to sign';
const data = {
data: message,
challenge: anotherChallenge,
};
const assertion = await generateAssertionIos(keyId, JSON.stringify(data));
// Verify the assertion with your server
await verifyAssertionWithServer({
assertion,
challenge,
keyId,
message,
});
import {
isPlayServicesAvailableAndroid,
prepareIntegrityTokenAndroid,
requestIntegrityTokenAndroid,
getAttestationAndroid,
} from 'react-native-secure-enclave-operations';
import uuid from 'react-native-uuid';
// NOTE: The server functions are placeholders.
// Check the server/ directory for a sample implementation.
// Check if Play Services is available
const isAvailable = await isPlayServicesAvailableAndroid();
if (!isAvailable) {
console.warn('Google Play Services is not available');
return;
}
// Prepare integrity token (should be called when app starts)
const cloudProjectNumber = 'your-cloud-project-number';
await prepareIntegrityTokenAndroid(cloudProjectNumber);
// Fetch a challenge from your server
const challenge = await fetchChallengeFromServer();
// Request an integrity token
const integrityToken = await requestIntegrityTokenAndroid(challenge);
// Send the integrity token to your server for verification
await verifyIntegrityTokenWithServer(integrityToken);
// Generate a key attestation (hardware-backed)
const keyId = uuid.v4();
const attestation = await getAttestationAndroid(challenge, keyId);
// Send the attestation to your server for verification
await verifyAttestationWithServer(attestation);
See the example app.
See this server/ directory for details on how to implement the server-side verification.
- Store the key ID securely, preferably in the device's Keychain
- Rotate keys periodically for enhanced security
- Use unique challenges for each attestation and assertion
- Implement proper error handling for failed attestations
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT
Made with create-react-native-library