expo-device-crypto
v1.0.0
Published
Crypto for Expo using device hardware capabilities
Maintainers
Readme
expo-device-crypto
🔒 Hardware-backed cryptography for Expo apps using Android Keystore/Strong Box and Apple Secure Enclave/Keychain.
Installation
npx expo install expo-device-cryptoIf you want to allow Face ID on iOS, add this to your app config:
{
"expo": {
"ios": {
"infoPlist": {
"NSFaceIDUsageDescription": "We use Face ID to protect your cryptographic keys."
}
}
}
}Supported Algorithms
✍️ Signature Algorithms
ECDSA_SECP256R1_SHA256Curve: P-256 / secp256r1. Hash: SHA-256.
RSA_SHA256Key size: 2048 bits. Padding: PKCS#1 v1.5. Hash: SHA-256.
RSA_SHA256_PSSKey size: 2048 bits. Padding: RSA-PSS (MGF1). Hash: SHA-256.
🔐 Encryption Algorithms
RSA_2048_PKCS1Key size: 2048 bits. Padding: PKCS#1 v1.5.
RSA_2048_OAEP_SHA1Key size: 2048 bits. Padding: OAEP with SHA-1 and MGF1.
ECIES_P256_AES256_GCMCurve: P-256 (secp256r1). Symmetric cipher: AES-256-GCM. Key derivation: HKDF-SHA256 (32-byte key from ECDH shared secret).
More coming soon...
Example
RSA with Biometric
import DeviceCrypto, {
AuthCheckResult,
AuthMethod,
EncryptionAlgorithm,
} from "expo-device-crypto";
const alias = "user-encryption-key";
const dataToEncrypt = "Sensitive data";
const algorithmType = EncryptionAlgorithm.RSA_2048_PKCS1;
const authMethod = AuthMethod.PASSCODE_OR_BIOMETRIC;
// 1) Ensure device authentication is configured (passcode at minimum)
const authStatus = DeviceCrypto.isAuthCheckAvailable();
if (authStatus !== AuthCheckResult.AVAILABLE) {
throw new Error(`Authentication unavailable: ${authStatus}`);
}
// 2) Generate an auth-protected RSA key pair
await DeviceCrypto.generateKeyPair(alias, {
algorithmType,
requireAuthentication: true,
authMethod, // iOS: defined at key generation;
});
// 3) Optional: retrieve/share public key with backend
const publicKeyPem = DeviceCrypto.getPublicKey(alias);
// 4) Encrypt with public key
const encrypted = await DeviceCrypto.encrypt(alias, dataToEncrypt, {
algorithmType,
});
// 5) Decrypt with private key
// Note: Data to decrypt must be in Base64 format.
// Note: This function should display the system user authentication prompt.
const decrypted = await DeviceCrypto.decrypt(alias, encrypted, {
algorithmType,
authMethod, // Android: defined when decrypting
});⚠️ Because iOS Keychain/Secure Enclave binds authentication policy to key creation,
authMethodmust be set ingenerateKeyPair. On Android Keystore, authentication is applied at key usage time, soauthMethodis provided in operations likesignanddecrypt.
📚 More examples
You can find additional usage examples in the examples directory of the main repository.
Methods
isAuthCheckAvailable(): AuthCheckResult- Returns device authentication availability (
AVAILABLE,NO_HARDWARE,UNAVAILABLE).
- Returns device authentication availability (
generateKeyPair(alias: string, options?: GenerateKeyPairOptions): Promise<GenerateKeyPairResult>- Creates a key pair for
aliasif it does not exist. - Defaults:
requireAuthentication = false,authMethod = PASSCODE_OR_BIOMETRIC.
- Creates a key pair for
getPublicKey(alias: string, options?: GetPublicKeyOptions): string | null- Returns public key in PEM format (or
nullif alias not found). - Defaults:
format = "PEM".
- Returns public key in PEM format (or
removeKeyPair(alias: string): boolean- Removes the key pair for the alias.
aliases(): string[]- Lists stored key aliases.
sign(alias: string, data: string, options?: SignOptions): Promise<string | null>- Signs UTF-8
datawith private key. - Defaults:
algorithmType = ECDSA_SECP256R1_SHA256,promptTitle = "Unlock",promptSubtitle = "Enter your PIN to continue",authMethod = PASSCODE_OR_BIOMETRIC.
- Signs UTF-8
verify(alias: string, data: string, signature: string, options?: VerifyOptions): Promise<boolean | null>- Verifies signature for UTF-8
data. - Signature must be in Base64 format.
- Default:
algorithmType = ECDSA_SECP256R1_SHA256.
- Verifies signature for UTF-8
encrypt(alias: string, data: string, options?: EncryptOptions): Promise<string | null>- Encrypts UTF-8
datawith public key. - Default:
algorithmType = RSA_2048_PKCS1. - For
algorithmType = ECIES_P256_AES256_GCM,peerPublicKeyis required inoptions.
- Encrypts UTF-8
decrypt(alias: string, data: string, options?: DecryptOptions): Promise<string | null>- Decrypts Base64
datawith private key. - Defaults:
algorithmType = RSA_2048_PKCS1,promptTitle = "Unlock",promptSubtitle = "Enter your PIN to continue",authMethod = PASSCODE_OR_BIOMETRIC. - For
algorithmType = ECIES_P256_AES256_GCM,peerPublicKeyis required inoptions.
- Decrypts Base64
Android only methods
isStrongBoxAvailable(): boolean- Returns
trueif StrongBox Keystore is supported on the device.
- Returns
Important
Enable Strong Box on Android
Use preferStrongBox: true when generating a key pair to request StrongBox-backed key storage when the device supports it.
import DeviceCrypto, { SigningAlgorithm } from "expo-device-crypto";
const alias = "user-signing-key";
// Optional: check availability first.
const hasStrongBox = DeviceCrypto.isStrongBoxAvailable();
await DeviceCrypto.generateKeyPair(alias, {
algorithmType: SigningAlgorithm.ECDSA_SECP256R1_SHA256,
preferStrongBox: true,
});If StrongBox is not available, Android falls back to the Trusted Execution Environment (TEE).
Secure Enclave support on iOS
On iOS, only ECDSA keys can use the Secure Enclave processor. RSA private-key operations are software-backed and handled by Apple’s system cryptographic services, which still provide strong isolation and protection.
ECIES - EC encryption schema
For library purposes, ECIES is referred to as an encryption algorithm for simplification, even though it is technically a broader encryption scheme.
