expo-device-crypto 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > ⚠️ This module is currently in beta and is not suitable for production use.
4
4
 
5
- 🔒 Hardware-backed cryptography for Expo apps using [Android Keystore](https://developer.android.com/privacy-and-security/keystore) and Apple [Secure Enclave](https://developer.apple.com/documentation/security/protecting-keys-with-the-secure-enclave)/[Keychain](https://developer.apple.com/documentation/security/keychain-services).
5
+ 🔒 Hardware-backed cryptography for Expo apps using [Android Keystore](https://developer.android.com/privacy-and-security/keystore)/[Strong Box](https://developer.android.com/privacy-and-security/keystore#StrongBoxKeyMint) and Apple [Secure Enclave](https://developer.apple.com/documentation/security/protecting-keys-with-the-secure-enclave)/[Keychain](https://developer.apple.com/documentation/security/keychain-services).
6
6
 
7
7
  ## Installation
8
8
 
@@ -176,10 +176,35 @@ const decrypted = await DeviceCrypto.decrypt(alias, encrypted ?? "", {
176
176
  - Decrypts Base64 `data` with private key.
177
177
  - Defaults: `algorithmType = RSA_2048_PKCS1`, `promptTitle = "Unlock"`, `promptSubtitle = "Enter your PIN to continue"`, `authMethod = PASSCODE_OR_BIOMETRIC`.
178
178
 
179
+ **Android only methods**
180
+
181
+ - `isStrongBoxAvailable(): boolean`
182
+ - Returns `true` if StrongBox Keystore is supported on the device.
183
+
179
184
  > ✅ JSDoc type definitions are available in `./src/DeviceCryptoModule.ts`.
180
185
 
181
186
  ## Important
182
187
 
188
+ ### Enable Strong Box on Android
189
+
190
+ Use `preferStrongBox: true` when generating a key pair to request [StrongBox-backed](https://developer.android.com/privacy-and-security/keystore#StrongBoxKeyMint) key storage when the device supports it.
191
+
192
+ ```ts
193
+ import DeviceCrypto, { SigningAlgorithm } from "expo-device-crypto";
194
+
195
+ const alias = "user-signing-key";
196
+
197
+ // Optional: check availability first.
198
+ const hasStrongBox = DeviceCrypto.isStrongBoxAvailable();
199
+
200
+ await DeviceCrypto.generateKeyPair(alias, {
201
+ algorithmType: SigningAlgorithm.ECDSA_SECP256R1_SHA256,
202
+ preferStrongBox: true,
203
+ });
204
+ ```
205
+
206
+ If StrongBox is not available, Android falls back to the Trusted Execution Environment (TEE).
207
+
183
208
  ### RSA algorithms on iOS
184
209
 
185
210
  Please note that RSA private-key operations are not performed in the [Secure Enclave processor](https://developer.apple.com/documentation/security/ksecattrtokenidsecureenclave?utm_source=chatgpt.com#Discussion). Instead, they are software-backed and handled by Apple’s system cryptographic services, which still provide strong isolation and protection.
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'expo.modules.devicecrypto'
4
- version = '0.2.1'
4
+ version = '0.2.2'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -35,7 +35,7 @@ android {
35
35
  namespace "expo.modules.devicecrypto"
36
36
  defaultConfig {
37
37
  versionCode 1
38
- versionName "0.2.1"
38
+ versionName "0.2.2"
39
39
  }
40
40
  lintOptions {
41
41
  abortOnError false
@@ -109,7 +109,8 @@ class DeviceCryptoModule : Module() {
109
109
  private fun buildECDSA(
110
110
  alias: String,
111
111
  digest: String,
112
- reqAuth: Boolean): KeyPairGenerator {
112
+ reqAuth: Boolean,
113
+ strongBox: Boolean): KeyPairGenerator {
113
114
  val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
114
115
  KEY_ALGORITHM_EC,
115
116
  "AndroidKeyStore"
@@ -120,7 +121,7 @@ class DeviceCryptoModule : Module() {
120
121
  PURPOSE_SIGN or PURPOSE_VERIFY
121
122
  ).run {
122
123
  setDigests(digest)
123
- setIsStrongBoxBacked(false) // TODO: Prefer strong box if available
124
+ setIsStrongBoxBacked(strongBox)
124
125
  setUserAuthenticationRequired(reqAuth)
125
126
  if (reqAuth) {
126
127
  setUserAuthenticationParameters(
@@ -138,7 +139,8 @@ class DeviceCryptoModule : Module() {
138
139
  alias: String,
139
140
  digest: String?,
140
141
  padding: String,
141
- reqAuth: Boolean): KeyPairGenerator {
142
+ reqAuth: Boolean,
143
+ strongBox: Boolean): KeyPairGenerator {
142
144
  val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
143
145
  KEY_ALGORITHM_RSA,
144
146
  "AndroidKeyStore"
@@ -152,7 +154,7 @@ class DeviceCryptoModule : Module() {
152
154
  setDigests(digest)
153
155
  }
154
156
  setEncryptionPaddings(padding)
155
- setIsStrongBoxBacked(false) // TODO: Prefer strong box if available
157
+ setIsStrongBoxBacked(strongBox)
156
158
  setUserAuthenticationRequired(reqAuth)
157
159
  if (reqAuth) {
158
160
  setUserAuthenticationParameters(
@@ -241,10 +243,13 @@ class DeviceCryptoModule : Module() {
241
243
  }
242
244
 
243
245
  val algoType = AlgorithmType.valueOf(o["algoType"] as String)
246
+ val preferStrongBox = o["preferStrongBox"] as Boolean
247
+ val strongBox = preferStrongBox && isStrongBoxAvailable()
248
+
244
249
  val kpg = when (algoType) {
245
- AlgorithmType.ECDSA_SECP256R1_SHA256 -> buildECDSA(alias, DIGEST_SHA256, reqAuth)
246
- AlgorithmType.RSA_2048_PKCS1 -> buildRSA(alias, null, ENCRYPTION_PADDING_RSA_PKCS1, reqAuth)
247
- AlgorithmType.RSA_2048_OAEP_SHA1 -> buildRSA(alias, DIGEST_SHA1, ENCRYPTION_PADDING_RSA_OAEP, reqAuth)
250
+ AlgorithmType.ECDSA_SECP256R1_SHA256 -> buildECDSA(alias, DIGEST_SHA256, reqAuth, strongBox)
251
+ AlgorithmType.RSA_2048_PKCS1 -> buildRSA(alias, null, ENCRYPTION_PADDING_RSA_PKCS1, reqAuth, strongBox)
252
+ AlgorithmType.RSA_2048_OAEP_SHA1 -> buildRSA(alias, DIGEST_SHA1, ENCRYPTION_PADDING_RSA_OAEP, reqAuth, strongBox)
248
253
  else -> throw Exception("INVALID_ALGORITHM_TYPE")
249
254
  }
250
255
 
@@ -411,6 +416,10 @@ class DeviceCryptoModule : Module() {
411
416
  return@Function isAuthCheckAvailable()
412
417
  }
413
418
 
419
+ Function("isStrongBoxAvailable") { ->
420
+ return@Function isStrongBoxAvailable()
421
+ }
422
+
414
423
  Function("generateKeyPair") { alias: String, o: Map<String, Any?> ->
415
424
  return@Function generateKeyPair(alias, o)
416
425
  }
@@ -46,28 +46,34 @@ export interface GenerateKeyPairOptions {
46
46
  * }
47
47
  * ```
48
48
  * @default AuthMethod.PASSCODE_OR_BIOMETRIC
49
- * @platform ios
49
+ * @platform ios 🍏
50
50
  */
51
51
  authMethod?: AuthMethod;
52
+ /**
53
+ * If the Strong Box is available, it will be used instead of the Trusted Execution Environment (TEE).
54
+ * @default false
55
+ * @platform android 🤖
56
+ */
57
+ preferStrongBox?: boolean;
52
58
  }
53
59
  interface BaseSignDecryptOptions {
54
60
  /**
55
61
  * The title of the prompt to show when authentication is required.
56
62
  * @default "Unlock"
57
- * @platform android
63
+ * @platform android 🤖
58
64
  */
59
65
  promptTitle?: string;
60
66
  /**
61
67
  * The subtitle of the prompt to show when authentication is required.
62
68
  * @default "Enter your PIN to continue"
63
- * @platform android
69
+ * @platform android 🤖
64
70
  */
65
71
  promptSubtitle?: string;
66
72
  /**
67
73
  * The method of authentication to use.
68
74
  * Note that on iOS you have to define it when generating the key pair.
69
75
  * @default AuthMethod.PASSCODE_OR_BIOMETRIC
70
- * @platform android
76
+ * @platform android 🤖
71
77
  */
72
78
  authMethod?: AuthMethod;
73
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceCrypto.types.d.ts","sourceRoot":"","sources":["../src/DeviceCrypto.types.ts"],"names":[],"mappings":"AAAA,oBAAY,qBAAqB;IAC/B,kBAAkB,uBAAuB;IACzC,uBAAuB,4BAA4B;IACnD,aAAa,kBAAkB;CAChC;AAED,oBAAY,eAAe;IACzB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;CAC5B;AAED,oBAAY,UAAU;IACpB,QAAQ,aAAa;IACrB,qBAAqB,0BAA0B;CAChD;AAED,oBAAY,gBAAgB;IAC1B,sBAAsB,2BAA2B;CAClD;AAED,oBAAY,mBAAmB;IAC7B,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,aAAa,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IACtD;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,UAAU,sBAAsB;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,UAAU,kBAAkB;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,UAAU,qBAAqB;IAC7B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,MAAM,WAAW,WAAY,SAAQ,sBAAsB,EAAE,kBAAkB;CAAG;AAClF,MAAM,WAAW,aAAc,SAAQ,kBAAkB;CAAG;AAE5D,MAAM,WAAW,cAAe,SAAQ,sBAAsB,EAAE,qBAAqB;CAAG;AACxF,MAAM,WAAW,cAAe,SAAQ,qBAAqB;CAAG;AAEhE,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB"}
1
+ {"version":3,"file":"DeviceCrypto.types.d.ts","sourceRoot":"","sources":["../src/DeviceCrypto.types.ts"],"names":[],"mappings":"AAAA,oBAAY,qBAAqB;IAC/B,kBAAkB,uBAAuB;IACzC,uBAAuB,4BAA4B;IACnD,aAAa,kBAAkB;CAChC;AAED,oBAAY,eAAe;IACzB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;CAC5B;AAED,oBAAY,UAAU;IACpB,QAAQ,aAAa;IACrB,qBAAqB,0BAA0B;CAChD;AAED,oBAAY,gBAAgB;IAC1B,sBAAsB,2BAA2B;CAClD;AAED,oBAAY,mBAAmB;IAC7B,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,aAAa,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IACtD;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,sBAAsB;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,UAAU,kBAAkB;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,UAAU,qBAAqB;IAC7B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,MAAM,WAAW,WAAY,SAAQ,sBAAsB,EAAE,kBAAkB;CAAG;AAClF,MAAM,WAAW,aAAc,SAAQ,kBAAkB;CAAG;AAE5D,MAAM,WAAW,cAAe,SAAQ,sBAAsB,EAAE,qBAAqB;CAAG;AACxF,MAAM,WAAW,cAAe,SAAQ,qBAAqB;CAAG;AAEhE,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB"}
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceCrypto.types.js","sourceRoot":"","sources":["../src/DeviceCrypto.types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,kEAAyC,CAAA;IACzC,4EAAmD,CAAA;IACnD,wDAA+B,CAAA;AACjC,CAAC,EAJW,qBAAqB,KAArB,qBAAqB,QAIhC;AAED,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,8CAA2B,CAAA;IAC3B,8CAA2B,CAAA;AAC7B,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAED,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,mCAAqB,CAAA;IACrB,6DAA+C,CAAA;AACjD,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB;AAED,MAAM,CAAN,IAAY,gBAEX;AAFD,WAAY,gBAAgB;IAC1B,qEAAiD,CAAA;AACnD,CAAC,EAFW,gBAAgB,KAAhB,gBAAgB,QAE3B;AAED,MAAM,CAAN,IAAY,mBAGX;AAHD,WAAY,mBAAmB;IAC7B,wDAAiC,CAAA;IACjC,gEAAyC,CAAA;AAC3C,CAAC,EAHW,mBAAmB,KAAnB,mBAAmB,QAG9B","sourcesContent":["export enum GenerateKeyPairResult {\n KEY_PAIR_GENERATED = \"KEY_PAIR_GENERATED\",\n KEY_PAIR_ALREADY_EXISTS = \"KEY_PAIR_ALREADY_EXISTS\",\n NOT_AVAILABLE = \"NOT_AVAILABLE\",\n}\n\nexport enum AuthCheckResult {\n AVAILABLE = \"AVAILABLE\",\n NO_HARDWARE = \"NO_HARDWARE\",\n UNAVAILABLE = \"UNAVAILABLE\",\n}\n\nexport enum AuthMethod {\n PASSCODE = \"PASSCODE\",\n PASSCODE_OR_BIOMETRIC = \"PASSCODE_OR_BIOMETRIC\",\n}\n\nexport enum SigningAlgorithm {\n ECDSA_SECP256R1_SHA256 = \"ECDSA_SECP256R1_SHA256\",\n}\n\nexport enum EncryptionAlgorithm {\n RSA_2048_PKCS1 = \"RSA_2048_PKCS1\",\n RSA_2048_OAEP_SHA1 = \"RSA_2048_OAEP_SHA1\",\n}\n\nexport interface GenerateKeyPairOptions {\n /**\n * The algorithm type of the key to generate.\n */\n algorithmType: SigningAlgorithm | EncryptionAlgorithm;\n /**\n * Whether to require authentication to sign.\n * Setting this to true will prompt biometric or passcode authentication before signing.\n *\n * Please check the *`isAuthCheckAvailable`* function to see if authentication is available.\n * If authentication is not available, generating a key pair will throw an error.\n * @default false\n */\n requireAuthentication?: boolean;\n /**\n * The method of authentication to use.\n * Note that on Android you have to define it when signing.\n *\n * If you want to allow to use Face ID, you need to add the following to your app.json config file:\n * ```json\n * \"ios\": {\n * \"infoPlist\": {\n * \"NSFaceIDUsageDescription\": \"We use Face ID to secure your data.\",\n * }\n * }\n * ```\n * @default AuthMethod.PASSCODE_OR_BIOMETRIC\n * @platform ios\n */\n authMethod?: AuthMethod;\n}\n\ninterface BaseSignDecryptOptions {\n /**\n * The title of the prompt to show when authentication is required.\n * @default \"Unlock\"\n * @platform android\n */\n promptTitle?: string;\n /**\n * The subtitle of the prompt to show when authentication is required.\n * @default \"Enter your PIN to continue\"\n * @platform android\n */\n promptSubtitle?: string;\n /**\n * The method of authentication to use.\n * Note that on iOS you have to define it when generating the key pair.\n * @default AuthMethod.PASSCODE_OR_BIOMETRIC\n * @platform android\n */\n authMethod?: AuthMethod;\n}\n\ninterface BaseSigningOptions {\n /**\n * The algorithm type of the key to use for signing.\n */\n algorithmType?: SigningAlgorithm;\n}\n\ninterface BaseEncryptionOptions {\n /**\n * The algorithm type of the key to use for encrypting.\n */\n algorithmType?: EncryptionAlgorithm;\n}\n\nexport interface SignOptions extends BaseSignDecryptOptions, BaseSigningOptions {}\nexport interface VerifyOptions extends BaseSigningOptions {}\n\nexport interface DecryptOptions extends BaseSignDecryptOptions, BaseEncryptionOptions {}\nexport interface EncryptOptions extends BaseEncryptionOptions {}\n\nexport interface GetPublicKeyOptions {\n /**\n * The format of the public key to return.\n * @default \"PEM\" (Base64 of PEM-encoded SubjectPublicKeyInfo (SPKI) for P‑256)\n */\n format?: \"PEM\";\n}\n"]}
1
+ {"version":3,"file":"DeviceCrypto.types.js","sourceRoot":"","sources":["../src/DeviceCrypto.types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,kEAAyC,CAAA;IACzC,4EAAmD,CAAA;IACnD,wDAA+B,CAAA;AACjC,CAAC,EAJW,qBAAqB,KAArB,qBAAqB,QAIhC;AAED,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,8CAA2B,CAAA;IAC3B,8CAA2B,CAAA;AAC7B,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAED,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,mCAAqB,CAAA;IACrB,6DAA+C,CAAA;AACjD,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB;AAED,MAAM,CAAN,IAAY,gBAEX;AAFD,WAAY,gBAAgB;IAC1B,qEAAiD,CAAA;AACnD,CAAC,EAFW,gBAAgB,KAAhB,gBAAgB,QAE3B;AAED,MAAM,CAAN,IAAY,mBAGX;AAHD,WAAY,mBAAmB;IAC7B,wDAAiC,CAAA;IACjC,gEAAyC,CAAA;AAC3C,CAAC,EAHW,mBAAmB,KAAnB,mBAAmB,QAG9B","sourcesContent":["export enum GenerateKeyPairResult {\n KEY_PAIR_GENERATED = \"KEY_PAIR_GENERATED\",\n KEY_PAIR_ALREADY_EXISTS = \"KEY_PAIR_ALREADY_EXISTS\",\n NOT_AVAILABLE = \"NOT_AVAILABLE\",\n}\n\nexport enum AuthCheckResult {\n AVAILABLE = \"AVAILABLE\",\n NO_HARDWARE = \"NO_HARDWARE\",\n UNAVAILABLE = \"UNAVAILABLE\",\n}\n\nexport enum AuthMethod {\n PASSCODE = \"PASSCODE\",\n PASSCODE_OR_BIOMETRIC = \"PASSCODE_OR_BIOMETRIC\",\n}\n\nexport enum SigningAlgorithm {\n ECDSA_SECP256R1_SHA256 = \"ECDSA_SECP256R1_SHA256\",\n}\n\nexport enum EncryptionAlgorithm {\n RSA_2048_PKCS1 = \"RSA_2048_PKCS1\",\n RSA_2048_OAEP_SHA1 = \"RSA_2048_OAEP_SHA1\",\n}\n\nexport interface GenerateKeyPairOptions {\n /**\n * The algorithm type of the key to generate.\n */\n algorithmType: SigningAlgorithm | EncryptionAlgorithm;\n /**\n * Whether to require authentication to sign.\n * Setting this to true will prompt biometric or passcode authentication before signing.\n *\n * Please check the *`isAuthCheckAvailable`* function to see if authentication is available.\n * If authentication is not available, generating a key pair will throw an error.\n * @default false\n */\n requireAuthentication?: boolean;\n /**\n * The method of authentication to use.\n * Note that on Android you have to define it when signing.\n *\n * If you want to allow to use Face ID, you need to add the following to your app.json config file:\n * ```json\n * \"ios\": {\n * \"infoPlist\": {\n * \"NSFaceIDUsageDescription\": \"We use Face ID to secure your data.\",\n * }\n * }\n * ```\n * @default AuthMethod.PASSCODE_OR_BIOMETRIC\n * @platform ios 🍏\n */\n authMethod?: AuthMethod;\n /**\n * If the Strong Box is available, it will be used instead of the Trusted Execution Environment (TEE).\n * @default false\n * @platform android 🤖\n */\n preferStrongBox?: boolean;\n}\n\ninterface BaseSignDecryptOptions {\n /**\n * The title of the prompt to show when authentication is required.\n * @default \"Unlock\"\n * @platform android 🤖\n */\n promptTitle?: string;\n /**\n * The subtitle of the prompt to show when authentication is required.\n * @default \"Enter your PIN to continue\"\n * @platform android 🤖\n */\n promptSubtitle?: string;\n /**\n * The method of authentication to use.\n * Note that on iOS you have to define it when generating the key pair.\n * @default AuthMethod.PASSCODE_OR_BIOMETRIC\n * @platform android 🤖\n */\n authMethod?: AuthMethod;\n}\n\ninterface BaseSigningOptions {\n /**\n * The algorithm type of the key to use for signing.\n */\n algorithmType?: SigningAlgorithm;\n}\n\ninterface BaseEncryptionOptions {\n /**\n * The algorithm type of the key to use for encrypting.\n */\n algorithmType?: EncryptionAlgorithm;\n}\n\nexport interface SignOptions extends BaseSignDecryptOptions, BaseSigningOptions {}\nexport interface VerifyOptions extends BaseSigningOptions {}\n\nexport interface DecryptOptions extends BaseSignDecryptOptions, BaseEncryptionOptions {}\nexport interface EncryptOptions extends BaseEncryptionOptions {}\n\nexport interface GetPublicKeyOptions {\n /**\n * The format of the public key to return.\n * @default \"PEM\" (Base64 of PEM-encoded SubjectPublicKeyInfo (SPKI) for P‑256)\n */\n format?: \"PEM\";\n}\n"]}
@@ -5,6 +5,12 @@ declare const _default: {
5
5
  * @returns The result of the operation.
6
6
  */
7
7
  isAuthCheckAvailable: () => AuthCheckResult;
8
+ /**
9
+ * Checks if the strong box is available .
10
+ * @returns The result of the operation.
11
+ * @platform android 🤖
12
+ */
13
+ isStrongBoxAvailable: () => boolean;
8
14
  /**
9
15
  * Creates a new ECDSA P‑256 key pair for the given alias, if it doesn’t already exist.
10
16
  * @param alias - The alias to use for the key pair.
@@ -34,12 +40,6 @@ declare const _default: {
34
40
  * @param alias - The alias to use for the key pair.
35
41
  * @param data - The data to sign.
36
42
  * @param options - The options for the operation.
37
- * @default {
38
- * algoType: SigningAlgorithm.ECDSA_SHA256,
39
- * promptTitle: "Unlock",
40
- * promptSubtitle: "Enter your PIN to continue",
41
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
42
- * }
43
43
  * @returns The signature.
44
44
  */
45
45
  sign: (alias: string, data: string, options?: SignOptions) => Promise<string | null>;
@@ -49,9 +49,6 @@ declare const _default: {
49
49
  * @param data - The data to verify in UTF-8 format.
50
50
  * @param signature - The signature to verify in Base64 format.
51
51
  * @param options - The options for the operation.
52
- * @default {
53
- * algoType: SigningAlgorithm.ECDSA_SHA256,
54
- * }
55
52
  * @returns True if the signature is valid, false otherwise.
56
53
  */
57
54
  verify: (alias: string, data: string, signature: string, options?: VerifyOptions) => Promise<boolean | null>;
@@ -71,12 +68,6 @@ declare const _default: {
71
68
  * @param alias - The alias to use for the key pair.
72
69
  * @param data - The data to decrypt in Base64 format.
73
70
  * @param options - The options for the operation.
74
- * @default {
75
- * algoType: EncryptionAlgorithm.RSA_2048_PKCS1,
76
- * promptTitle: "Unlock",
77
- * promptSubtitle: "Enter your PIN to continue",
78
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
79
- * }
80
71
  * @returns The decrypted data.
81
72
  */
82
73
  decrypt: (alias: string, data: string, options?: DecryptOptions) => Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceCryptoModule.d.ts","sourceRoot":"","sources":["../src/DeviceCryptoModule.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EAEnB,WAAW,EACX,cAAc,EACd,aAAa,EAEb,cAAc,EAEf,MAAM,sBAAsB,CAAC;;IA6B5B;;;OAGG;gCAtBqB,eAAe;IAwBvC;;;;OAIG;6BAC4B,MAAM,YAAY,sBAAsB;IAQvE;;;;;OAKG;0BACmB,MAAM,YAAY,mBAAmB;IAQ3D;;;;OAIG;2BApDkB,MAAM,KAAG,OAAO;IAsDrC;;;OAGG;mBAxDQ,MAAM,EAAE;IA0DnB;;;;;;;;;;;;OAYG;kBACiB,MAAM,QAAQ,MAAM,YAAY,WAAW;IAS/D;;;;;;;;;;OAUG;oBAEM,MAAM,QACP,MAAM,aACD,MAAM,YACP,aAAa;IAOzB;;;;;;;;;OASG;qBACoB,MAAM,QAAQ,MAAM,YAAY,cAAc;IAMrE;;;;;;;;;;;;OAYG;qBACoB,MAAM,QAAQ,MAAM,YAAY,cAAc;;AArHvE,wBA8HE"}
1
+ {"version":3,"file":"DeviceCryptoModule.d.ts","sourceRoot":"","sources":["../src/DeviceCryptoModule.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EAEnB,WAAW,EACX,cAAc,EACd,aAAa,EAEb,cAAc,EAEf,MAAM,sBAAsB,CAAC;;IA8B5B;;;OAGG;gCAvBqB,eAAe;IAyBvC;;;;OAIG;gCA5BqB,OAAO;IA8B/B;;;;OAIG;6BAC4B,MAAM,YAAY,sBAAsB;IASvE;;;;;OAKG;0BACmB,MAAM,YAAY,mBAAmB;IAQ3D;;;;OAIG;2BA3DkB,MAAM,KAAG,OAAO;IA6DrC;;;OAGG;mBA/DQ,MAAM,EAAE;IAiEnB;;;;;;OAMG;kBACiB,MAAM,QAAQ,MAAM,YAAY,WAAW;IAS/D;;;;;;;OAOG;oBAEM,MAAM,QACP,MAAM,aACD,MAAM,YACP,aAAa;IAOzB;;;;;;;;;OASG;qBACoB,MAAM,QAAQ,MAAM,YAAY,cAAc;IAMrE;;;;;;OAMG;qBACoB,MAAM,QAAQ,MAAM,YAAY,cAAc;;AA7GvE,wBAsHE"}
@@ -12,6 +12,12 @@ export default {
12
12
  * @returns The result of the operation.
13
13
  */
14
14
  isAuthCheckAvailable: module.isAuthCheckAvailable,
15
+ /**
16
+ * Checks if the strong box is available .
17
+ * @returns The result of the operation.
18
+ * @platform android 🤖
19
+ */
20
+ isStrongBoxAvailable: module.isStrongBoxAvailable,
15
21
  /**
16
22
  * Creates a new ECDSA P‑256 key pair for the given alias, if it doesn’t already exist.
17
23
  * @param alias - The alias to use for the key pair.
@@ -22,6 +28,7 @@ export default {
22
28
  algoType: options?.algorithmType,
23
29
  reqAuth: options?.requireAuthentication ?? false,
24
30
  authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,
31
+ preferStrongBox: options?.preferStrongBox ?? false,
25
32
  };
26
33
  return module.generateKeyPair(alias, o);
27
34
  },
@@ -56,12 +63,6 @@ export default {
56
63
  * @param alias - The alias to use for the key pair.
57
64
  * @param data - The data to sign.
58
65
  * @param options - The options for the operation.
59
- * @default {
60
- * algoType: SigningAlgorithm.ECDSA_SHA256,
61
- * promptTitle: "Unlock",
62
- * promptSubtitle: "Enter your PIN to continue",
63
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
64
- * }
65
66
  * @returns The signature.
66
67
  */
67
68
  sign: async (alias, data, options) => {
@@ -79,9 +80,6 @@ export default {
79
80
  * @param data - The data to verify in UTF-8 format.
80
81
  * @param signature - The signature to verify in Base64 format.
81
82
  * @param options - The options for the operation.
82
- * @default {
83
- * algoType: SigningAlgorithm.ECDSA_SHA256,
84
- * }
85
83
  * @returns True if the signature is valid, false otherwise.
86
84
  */
87
85
  verify: async (alias, data, signature, options) => {
@@ -111,12 +109,6 @@ export default {
111
109
  * @param alias - The alias to use for the key pair.
112
110
  * @param data - The data to decrypt in Base64 format.
113
111
  * @param options - The options for the operation.
114
- * @default {
115
- * algoType: EncryptionAlgorithm.RSA_2048_PKCS1,
116
- * promptTitle: "Unlock",
117
- * promptSubtitle: "Enter your PIN to continue",
118
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
119
- * }
120
112
  * @returns The decrypted data.
121
113
  */
122
114
  decrypt: async (alias, data, options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceCryptoModule.js","sourceRoot":"","sources":["../src/DeviceCryptoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAEzD,OAAO,EAKL,UAAU,EAIV,gBAAgB,EAEhB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,SAAS,WAAW,CAAC,MAAc,EAAE,KAAK,GAAG,MAAM;IACjD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAE/D,OAAO,cAAc,KAAK,UAAU,OAAO,cAAc,KAAK,SAAS,CAAC;AAC1E,CAAC;AAmBD,MAAM,MAAM,GAAG,mBAAmB,CAAqB,cAAc,CAAC,CAAC;AAEvE,eAAe;IACb;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;IACjD;;;;OAIG;IACH,eAAe,EAAE,KAAK,EAAE,KAAa,EAAE,OAAgC,EAAE,EAAE;QACzE,MAAM,CAAC,GAAG;YACR,QAAQ,EAAE,OAAO,EAAE,aAAa;YAChC,OAAO,EAAE,OAAO,EAAE,qBAAqB,IAAI,KAAK;YAChD,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,UAAU,CAAC,qBAAqB;SACpE,CAAC;QACF,OAAO,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD;;;;;OAKG;IACH,YAAY,EAAE,CAAC,KAAa,EAAE,OAA6B,EAAE,EAAE;QAC7D,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,OAAO,EAAE,MAAM,KAAK,KAAK,EAAE,CAAC;YAC9B,OAAO,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC9C,CAAC;IACD;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC,aAAa;IACnC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,OAAO;IACvB;;;;;;;;;;;;OAYG;IACH,IAAI,EAAE,KAAK,EAAE,KAAa,EAAE,IAAY,EAAE,OAAqB,EAAE,EAAE;QACjE,MAAM,CAAC,GAAG;YACR,KAAK,EAAE,OAAO,EAAE,WAAW,IAAI,QAAQ;YACvC,QAAQ,EAAE,OAAO,EAAE,cAAc,IAAI,4BAA4B;YACjE,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,UAAU,CAAC,qBAAqB;YACnE,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,gBAAgB,CAAC,sBAAsB;SAC5E,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IACD;;;;;;;;;;OAUG;IACH,MAAM,EAAE,KAAK,EACX,KAAa,EACb,IAAY,EACZ,SAAiB,EACjB,OAAuB,EACvB,EAAE;QACF,MAAM,CAAC,GAAG;YACR,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,gBAAgB,CAAC,sBAAsB;SAC5E,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IACD;;;;;;;;;OASG;IACH,OAAO,EAAE,KAAK,EAAE,KAAa,EAAE,IAAY,EAAE,OAAwB,EAAE,EAAE;QACvE,MAAM,CAAC,GAAG;YACR,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,mBAAmB,CAAC,cAAc;SACvE,CAAC;QACF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD;;;;;;;;;;;;OAYG;IACH,OAAO,EAAE,KAAK,EAAE,KAAa,EAAE,IAAY,EAAE,OAAwB,EAAE,EAAE;QACvE,MAAM,CAAC,GAAG;YACR,KAAK,EAAE,OAAO,EAAE,WAAW,IAAI,QAAQ;YACvC,QAAQ,EAAE,OAAO,EAAE,cAAc,IAAI,4BAA4B;YACjE,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,UAAU,CAAC,qBAAqB;YACnE,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,mBAAmB,CAAC,cAAc;SACvE,CAAC;QACF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;CACF,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n AuthCheckResult,\n GenerateKeyPairOptions,\n GenerateKeyPairResult,\n GetPublicKeyOptions,\n AuthMethod,\n SignOptions,\n DecryptOptions,\n VerifyOptions,\n SigningAlgorithm,\n EncryptOptions,\n EncryptionAlgorithm,\n} from \"./DeviceCrypto.types\";\n\nfunction base64ToPem(base64: string, label = \"DATA\") {\n const normalized = base64.replace(/\\s+/g, \"\");\n const wrapped = normalized.match(/.{1,64}/g)?.join(\"\\n\") ?? \"\";\n\n return `-----BEGIN ${label}-----\\n${wrapped}\\n-----END ${label}-----\\n`;\n}\n\ndeclare class DeviceCryptoModule extends NativeModule {\n isAuthCheckAvailable(): AuthCheckResult;\n generateKeyPair(alias: string, o: any): GenerateKeyPairResult;\n getPublicKey(alias: string): string | null;\n removeKeyPair(alias: string): boolean;\n aliases(): string[];\n sign(alias: string, data: string, o: any): Promise<string | null>;\n verify(\n alias: string,\n data: string,\n signature: string,\n o: any\n ): boolean | null;\n encrypt(alias: string, data: string, o: any): Promise<string | null>;\n decrypt(alias: string, data: string, o: any): Promise<string | null>;\n}\n\nconst module = requireNativeModule<DeviceCryptoModule>(\"DeviceCrypto\");\n\nexport default {\n /**\n * Checks if the biometric or passcode authentication is available.\n * @returns The result of the operation.\n */\n isAuthCheckAvailable: module.isAuthCheckAvailable,\n /**\n * Creates a new ECDSA P‑256 key pair for the given alias, if it doesn’t already exist.\n * @param alias - The alias to use for the key pair.\n * @returns The result of the operation.\n */\n generateKeyPair: async (alias: string, options?: GenerateKeyPairOptions) => {\n const o = {\n algoType: options?.algorithmType,\n reqAuth: options?.requireAuthentication ?? false,\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n };\n return module.generateKeyPair(alias, o);\n },\n /**\n * Returns the public key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param options - The options for the operation.\n * @returns The public key.\n */\n getPublicKey: (alias: string, options?: GetPublicKeyOptions) => {\n const publicKey = module.getPublicKey(alias);\n if (!publicKey) return null;\n if (options?.format === \"PEM\") {\n return base64ToPem(publicKey, \"PUBLIC KEY\");\n }\n return base64ToPem(publicKey, \"PUBLIC KEY\");\n },\n /**\n * Removes the key pair for the given alias.\n * @param alias - The alias to use for the key pair.\n * @returns True if the key pair was removed, false otherwise.\n */\n removeKeyPair: module.removeKeyPair,\n /**\n * Lists the aliases for the key pairs.\n * @returns The aliases.\n */\n aliases: module.aliases,\n /**\n * Signs the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to sign.\n * @param options - The options for the operation.\n * @default { \n * algoType: SigningAlgorithm.ECDSA_SHA256, \n * promptTitle: \"Unlock\", \n * promptSubtitle: \"Enter your PIN to continue\", \n * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC \n * }\n * @returns The signature.\n */\n sign: async (alias: string, data: string, options?: SignOptions) => {\n const o = {\n title: options?.promptTitle ?? \"Unlock\",\n subtitle: options?.promptSubtitle ?? \"Enter your PIN to continue\",\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n algoType: options?.algorithmType ?? SigningAlgorithm.ECDSA_SECP256R1_SHA256,\n };\n return module.sign(alias, data, o);\n },\n /**\n * Verifies the given data with the signature for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to verify in UTF-8 format.\n * @param signature - The signature to verify in Base64 format.\n * @param options - The options for the operation.\n * @default { \n * algoType: SigningAlgorithm.ECDSA_SHA256, \n * }\n * @returns True if the signature is valid, false otherwise.\n */\n verify: async (\n alias: string,\n data: string,\n signature: string,\n options?: VerifyOptions\n ) => {\n const o = {\n algoType: options?.algorithmType ?? SigningAlgorithm.ECDSA_SECP256R1_SHA256,\n };\n return module.verify(alias, data, signature, o);\n },\n /**\n * Signs the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to sign in UTF-8 format.\n * @param options - The options for the operation.\n * @default { \n * algoType: EncryptionAlgorithm.RSA_2048_PKCS1, \n * }\n * @returns The signature.\n */\n encrypt: async (alias: string, data: string, options?: EncryptOptions) => {\n const o = {\n algoType: options?.algorithmType ?? EncryptionAlgorithm.RSA_2048_PKCS1,\n };\n return module.encrypt(alias, data, o);\n },\n /**\n * Decrypts the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to decrypt in Base64 format.\n * @param options - The options for the operation.\n * @default { \n * algoType: EncryptionAlgorithm.RSA_2048_PKCS1, \n * promptTitle: \"Unlock\", \n * promptSubtitle: \"Enter your PIN to continue\", \n * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC \n * }\n * @returns The decrypted data.\n */\n decrypt: async (alias: string, data: string, options?: DecryptOptions) => {\n const o = {\n title: options?.promptTitle ?? \"Unlock\",\n subtitle: options?.promptSubtitle ?? \"Enter your PIN to continue\",\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n algoType: options?.algorithmType ?? EncryptionAlgorithm.RSA_2048_PKCS1,\n };\n return module.decrypt(alias, data, o);\n },\n};"]}
1
+ {"version":3,"file":"DeviceCryptoModule.js","sourceRoot":"","sources":["../src/DeviceCryptoModule.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n AuthCheckResult,\n GenerateKeyPairOptions,\n GenerateKeyPairResult,\n GetPublicKeyOptions,\n AuthMethod,\n SignOptions,\n DecryptOptions,\n VerifyOptions,\n SigningAlgorithm,\n EncryptOptions,\n EncryptionAlgorithm,\n} from \"./DeviceCrypto.types\";\n\nfunction base64ToPem(base64: string, label = \"DATA\") {\n const normalized = base64.replace(/\\s+/g, \"\");\n const wrapped = normalized.match(/.{1,64}/g)?.join(\"\\n\") ?? \"\";\n\n return `-----BEGIN ${label}-----\\n${wrapped}\\n-----END ${label}-----\\n`;\n}\n\ndeclare class DeviceCryptoModule extends NativeModule {\n isAuthCheckAvailable(): AuthCheckResult;\n isStrongBoxAvailable(): boolean;\n generateKeyPair(alias: string, o: any): GenerateKeyPairResult;\n getPublicKey(alias: string): string | null;\n removeKeyPair(alias: string): boolean;\n aliases(): string[];\n sign(alias: string, data: string, o: any): Promise<string | null>;\n verify(\n alias: string,\n data: string,\n signature: string,\n o: any\n ): boolean | null;\n encrypt(alias: string, data: string, o: any): Promise<string | null>;\n decrypt(alias: string, data: string, o: any): Promise<string | null>;\n}\n\nconst module = requireNativeModule<DeviceCryptoModule>(\"DeviceCrypto\");\n\nexport default {\n /**\n * Checks if the biometric or passcode authentication is available.\n * @returns The result of the operation.\n */\n isAuthCheckAvailable: module.isAuthCheckAvailable,\n /**\n * Checks if the strong box is available .\n * @returns The result of the operation.\n * @platform android 🤖\n */\n isStrongBoxAvailable: module.isStrongBoxAvailable,\n /**\n * Creates a new ECDSA P‑256 key pair for the given alias, if it doesn’t already exist.\n * @param alias - The alias to use for the key pair.\n * @returns The result of the operation.\n */\n generateKeyPair: async (alias: string, options?: GenerateKeyPairOptions) => {\n const o = {\n algoType: options?.algorithmType,\n reqAuth: options?.requireAuthentication ?? false,\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n preferStrongBox: options?.preferStrongBox ?? false,\n };\n return module.generateKeyPair(alias, o);\n },\n /**\n * Returns the public key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param options - The options for the operation.\n * @returns The public key.\n */\n getPublicKey: (alias: string, options?: GetPublicKeyOptions) => {\n const publicKey = module.getPublicKey(alias);\n if (!publicKey) return null;\n if (options?.format === \"PEM\") {\n return base64ToPem(publicKey, \"PUBLIC KEY\");\n }\n return base64ToPem(publicKey, \"PUBLIC KEY\");\n },\n /**\n * Removes the key pair for the given alias.\n * @param alias - The alias to use for the key pair.\n * @returns True if the key pair was removed, false otherwise.\n */\n removeKeyPair: module.removeKeyPair,\n /**\n * Lists the aliases for the key pairs.\n * @returns The aliases.\n */\n aliases: module.aliases,\n /**\n * Signs the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to sign.\n * @param options - The options for the operation.\n * @returns The signature.\n */\n sign: async (alias: string, data: string, options?: SignOptions) => {\n const o = {\n title: options?.promptTitle ?? \"Unlock\",\n subtitle: options?.promptSubtitle ?? \"Enter your PIN to continue\",\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n algoType: options?.algorithmType ?? SigningAlgorithm.ECDSA_SECP256R1_SHA256,\n };\n return module.sign(alias, data, o);\n },\n /**\n * Verifies the given data with the signature for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to verify in UTF-8 format.\n * @param signature - The signature to verify in Base64 format.\n * @param options - The options for the operation.\n * @returns True if the signature is valid, false otherwise.\n */\n verify: async (\n alias: string,\n data: string,\n signature: string,\n options?: VerifyOptions\n ) => {\n const o = {\n algoType: options?.algorithmType ?? SigningAlgorithm.ECDSA_SECP256R1_SHA256,\n };\n return module.verify(alias, data, signature, o);\n },\n /**\n * Signs the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to sign in UTF-8 format.\n * @param options - The options for the operation.\n * @default { \n * algoType: EncryptionAlgorithm.RSA_2048_PKCS1, \n * }\n * @returns The signature.\n */\n encrypt: async (alias: string, data: string, options?: EncryptOptions) => {\n const o = {\n algoType: options?.algorithmType ?? EncryptionAlgorithm.RSA_2048_PKCS1,\n };\n return module.encrypt(alias, data, o);\n },\n /**\n * Decrypts the given data with the private key for the given alias.\n * @param alias - The alias to use for the key pair.\n * @param data - The data to decrypt in Base64 format.\n * @param options - The options for the operation.\n * @returns The decrypted data.\n */\n decrypt: async (alias: string, data: string, options?: DecryptOptions) => {\n const o = {\n title: options?.promptTitle ?? \"Unlock\",\n subtitle: options?.promptSubtitle ?? \"Enter your PIN to continue\",\n authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,\n algoType: options?.algorithmType ?? EncryptionAlgorithm.RSA_2048_PKCS1,\n };\n return module.decrypt(alias, data, o);\n },\n};"]}
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'DeviceCrypto'
3
- s.version = '0.2.1'
3
+ s.version = '0.2.2'
4
4
  s.summary = 'Device crypto'
5
5
  s.description = 'Device crypto for Expo using device hardware capabilities'
6
6
  s.author = 'Piotr Pietras'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-device-crypto",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Crypto for Expo using device hardware capabilities",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -51,29 +51,35 @@ export interface GenerateKeyPairOptions {
51
51
  * }
52
52
  * ```
53
53
  * @default AuthMethod.PASSCODE_OR_BIOMETRIC
54
- * @platform ios
54
+ * @platform ios 🍏
55
55
  */
56
56
  authMethod?: AuthMethod;
57
+ /**
58
+ * If the Strong Box is available, it will be used instead of the Trusted Execution Environment (TEE).
59
+ * @default false
60
+ * @platform android 🤖
61
+ */
62
+ preferStrongBox?: boolean;
57
63
  }
58
64
 
59
65
  interface BaseSignDecryptOptions {
60
66
  /**
61
67
  * The title of the prompt to show when authentication is required.
62
68
  * @default "Unlock"
63
- * @platform android
69
+ * @platform android 🤖
64
70
  */
65
71
  promptTitle?: string;
66
72
  /**
67
73
  * The subtitle of the prompt to show when authentication is required.
68
74
  * @default "Enter your PIN to continue"
69
- * @platform android
75
+ * @platform android 🤖
70
76
  */
71
77
  promptSubtitle?: string;
72
78
  /**
73
79
  * The method of authentication to use.
74
80
  * Note that on iOS you have to define it when generating the key pair.
75
81
  * @default AuthMethod.PASSCODE_OR_BIOMETRIC
76
- * @platform android
82
+ * @platform android 🤖
77
83
  */
78
84
  authMethod?: AuthMethod;
79
85
  }
@@ -23,6 +23,7 @@ function base64ToPem(base64: string, label = "DATA") {
23
23
 
24
24
  declare class DeviceCryptoModule extends NativeModule {
25
25
  isAuthCheckAvailable(): AuthCheckResult;
26
+ isStrongBoxAvailable(): boolean;
26
27
  generateKeyPair(alias: string, o: any): GenerateKeyPairResult;
27
28
  getPublicKey(alias: string): string | null;
28
29
  removeKeyPair(alias: string): boolean;
@@ -46,6 +47,12 @@ export default {
46
47
  * @returns The result of the operation.
47
48
  */
48
49
  isAuthCheckAvailable: module.isAuthCheckAvailable,
50
+ /**
51
+ * Checks if the strong box is available .
52
+ * @returns The result of the operation.
53
+ * @platform android 🤖
54
+ */
55
+ isStrongBoxAvailable: module.isStrongBoxAvailable,
49
56
  /**
50
57
  * Creates a new ECDSA P‑256 key pair for the given alias, if it doesn’t already exist.
51
58
  * @param alias - The alias to use for the key pair.
@@ -56,6 +63,7 @@ export default {
56
63
  algoType: options?.algorithmType,
57
64
  reqAuth: options?.requireAuthentication ?? false,
58
65
  authMethod: options?.authMethod ?? AuthMethod.PASSCODE_OR_BIOMETRIC,
66
+ preferStrongBox: options?.preferStrongBox ?? false,
59
67
  };
60
68
  return module.generateKeyPair(alias, o);
61
69
  },
@@ -89,12 +97,6 @@ export default {
89
97
  * @param alias - The alias to use for the key pair.
90
98
  * @param data - The data to sign.
91
99
  * @param options - The options for the operation.
92
- * @default {
93
- * algoType: SigningAlgorithm.ECDSA_SHA256,
94
- * promptTitle: "Unlock",
95
- * promptSubtitle: "Enter your PIN to continue",
96
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
97
- * }
98
100
  * @returns The signature.
99
101
  */
100
102
  sign: async (alias: string, data: string, options?: SignOptions) => {
@@ -112,9 +114,6 @@ export default {
112
114
  * @param data - The data to verify in UTF-8 format.
113
115
  * @param signature - The signature to verify in Base64 format.
114
116
  * @param options - The options for the operation.
115
- * @default {
116
- * algoType: SigningAlgorithm.ECDSA_SHA256,
117
- * }
118
117
  * @returns True if the signature is valid, false otherwise.
119
118
  */
120
119
  verify: async (
@@ -149,12 +148,6 @@ export default {
149
148
  * @param alias - The alias to use for the key pair.
150
149
  * @param data - The data to decrypt in Base64 format.
151
150
  * @param options - The options for the operation.
152
- * @default {
153
- * algoType: EncryptionAlgorithm.RSA_2048_PKCS1,
154
- * promptTitle: "Unlock",
155
- * promptSubtitle: "Enter your PIN to continue",
156
- * authMethod: AuthMethod.PASSCODE_OR_BIOMETRIC
157
- * }
158
151
  * @returns The decrypted data.
159
152
  */
160
153
  decrypt: async (alias: string, data: string, options?: DecryptOptions) => {