expo-device-crypto 0.1.0 → 0.2.0

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 and Apple Secure Enclave/Keychain where available.
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).
6
6
 
7
7
  ## Installation
8
8
 
@@ -26,42 +26,35 @@ If you want to allow Face ID on iOS, add this to your app config:
26
26
 
27
27
  ## Supported Algorithms
28
28
 
29
- ### ECDSA (`ECDSA_SECP256R1_SHA256`)
29
+ ### Signature Algorithms
30
30
 
31
- - **Type:** Digital signature algorithm (asymmetric).
32
- - **Curve:** P-256 / secp256r1.
33
- - **Hash:** SHA-256.
34
- - **Use it for:** Authentication challenges, message signing, and tamper detection.
31
+ - #### `ECDSA_SECP256R1_SHA256`
35
32
 
36
- ### RSA (`RSA_2048_PKCS1`)
33
+ **Curve:** P-256 / secp256r1. </br>
34
+ **Hash:** SHA-256. </br>
35
+ **Use it for:** Authentication challenges, message signing, and tamper detection.
37
36
 
38
- - **Type:** Asymmetric encryption algorithm.
39
- - **Key size:** 2048 bits.
40
- - **Padding:** PKCS#1 v1.5.
41
- - **Use it for:** Encrypting small secrets that only the private key holder should decrypt.
37
+ ### Encryption Algorithms
42
38
 
43
- ## Biometric and Passcode Protection
39
+ - #### `RSA_2048_PKCS1`
44
40
 
45
- You can bind private key usage to user authentication with:
41
+ **Key size:** 2048 bits. </br>
42
+ **Padding:** PKCS#1 v1.5. </br>
43
+ **Use it for:** Encrypting small secrets that only the private key holder should decrypt.
46
44
 
47
- - `requireAuthentication: true` when creating a key pair. (set to `false` to allow signing and decryption without authentication prompts)
48
- - Use `AuthMethod.PASSCODE` or `AuthMethod.PASSCODE_OR_BIOMETRIC` to specify whether authentication should require only a passcode or allow biometrics when available.
45
+ - #### `RSA_2048_OAEP_SHA1`
49
46
 
50
- Before using authentication-protected keys, verify that device authentication is available. If the user has not enabled at least a passcode, this function returns `AuthCheckResult.UNAVAILABLE`.
47
+ **Key size:** 2048 bits. </br>
48
+ **Padding:** OAEP with SHA-1 and MGF1. </br>
49
+ **Use it for:** Encrypting small secrets with stronger padding than PKCS#1 v1.5 when interoperating with OAEP SHA-1 systems.
51
50
 
52
- ```ts
53
- import DeviceCrypto, { AuthCheckResult } from "expo-device-crypto";
54
-
55
- const authStatus = DeviceCrypto.isAuthCheckAvailable();
56
- if (authStatus !== AuthCheckResult.AVAILABLE) {
57
- throw new Error(`Authentication unavailable: ${authStatus}`);
58
- }
59
- ```
51
+ More coming soon
60
52
 
61
53
  ## Example: ECDSA with Biometric
62
54
 
63
55
  ```ts
64
56
  import DeviceCrypto, {
57
+ AuthCheckResult,
65
58
  AuthMethod,
66
59
  SigningAlgorithm,
67
60
  } from "expo-device-crypto";
@@ -71,24 +64,31 @@ const payload = "Sign this challenge payload";
71
64
  const algorithmType = SigningAlgorithm.ECDSA_SECP256R1_SHA256;
72
65
  const authMethod = AuthMethod.PASSCODE_OR_BIOMETRIC;
73
66
 
74
- // 1) Generate an auth-protected ECDSA key pair
67
+ // 1) Ensure device authentication is configured (passcode at minimum)
68
+ const authStatus = DeviceCrypto.isAuthCheckAvailable();
69
+ if (authStatus !== AuthCheckResult.AVAILABLE) {
70
+ throw new Error(`Authentication unavailable: ${authStatus}`);
71
+ }
72
+
73
+ // 2) Generate an auth-protected ECDSA key pair
75
74
  await DeviceCrypto.generateKeyPair(alias, {
76
75
  requireAuthentication: true,
77
76
  authMethod, // iOS: defined at key generation;
78
77
  algorithmType,
79
78
  });
80
79
 
81
- // 2) Optional: share public key with backend
80
+ // 3) Optional: share public key with backend
82
81
  const publicKeyPem = DeviceCrypto.getPublicKey(alias, { format: "PEM" });
83
82
 
84
- // 3) Sign with private key (prompts biometric/passcode on protected keys)
83
+ // 4) Sign with private key (prompts biometric/passcode on protected keys)
85
84
  // Note: The data to sign must be in UTF-8 format.
85
+ // Note: This function should display the system user authentication prompt.
86
86
  const signature = await DeviceCrypto.sign(alias, payload, {
87
87
  algorithmType,
88
88
  authMethod, // Android: defined when signing
89
89
  });
90
90
 
91
- // 4) Verify locally (usually done server-side with stored public key)
91
+ // 5) Verify locally (usually done server-side with stored public key)
92
92
  const isValid = await DeviceCrypto.verify(alias, payload, signature ?? "", {
93
93
  algorithmType,
94
94
  });
@@ -98,6 +98,7 @@ const isValid = await DeviceCrypto.verify(alias, payload, signature ?? "", {
98
98
 
99
99
  ```ts
100
100
  import DeviceCrypto, {
101
+ AuthCheckResult,
101
102
  AuthMethod,
102
103
  EncryptionAlgorithm,
103
104
  } from "expo-device-crypto";
@@ -107,26 +108,72 @@ const secret = "Sensitive token";
107
108
  const algorithmType = EncryptionAlgorithm.RSA_2048_PKCS1;
108
109
  const authMethod = AuthMethod.PASSCODE_OR_BIOMETRIC;
109
110
 
110
- // 1) Generate an auth-protected RSA key pair
111
+ // 1) Ensure device authentication is configured (passcode at minimum)
112
+ const authStatus = DeviceCrypto.isAuthCheckAvailable();
113
+ if (authStatus !== AuthCheckResult.AVAILABLE) {
114
+ throw new Error(`Authentication unavailable: ${authStatus}`);
115
+ }
116
+
117
+ // 2) Generate an auth-protected RSA key pair
111
118
  await DeviceCrypto.generateKeyPair(alias, {
112
119
  algorithmType,
113
120
  requireAuthentication: true,
114
121
  authMethod, // iOS: defined at key generation;
115
122
  });
116
123
 
117
- // 2) Optional: retrieve/share public key with backend
124
+ // 3) Optional: retrieve/share public key with backend
118
125
  const publicKeyPem = DeviceCrypto.getPublicKey(alias, { format: "PEM" });
119
126
 
120
- // 3) Encrypt with public key
127
+ // 4) Encrypt with public key
121
128
  const encrypted = await DeviceCrypto.encrypt(alias, secret, {
122
129
  algorithmType,
123
130
  });
124
131
 
125
- // 4) Decrypt with private key (prompts biometric/passcode on protected keys)
126
- // Note: Data to encrypt must be in Base64 format.
132
+ // 5) Decrypt with private key (prompts biometric/passcode on protected keys)
133
+ // Note: Data to decrypt must be in Base64 format.
134
+ // Note: This function should display the system user authentication prompt.
127
135
  const decrypted = await DeviceCrypto.decrypt(alias, encrypted ?? "", {
128
136
  algorithmType,
129
137
  authMethod, // Android: defined when decrypting
130
138
  });
131
139
  ```
132
140
 
141
+ > ⚠️ Because iOS Keychain/Secure Enclave binds authentication policy to key creation, `authMethod` must be set in `generateKeyPair`. On Android Keystore, authentication is applied at key usage time, so `authMethod` is provided in operations like `sign` and `decrypt`.
142
+
143
+ ### Methods
144
+
145
+ - `isAuthCheckAvailable(): AuthCheckResult`
146
+ - Returns device authentication availability (`AVAILABLE`, `NO_HARDWARE`, `UNAVAILABLE`).
147
+
148
+ - `generateKeyPair(alias: string, options?: GenerateKeyPairOptions): Promise<GenerateKeyPairResult>`
149
+ - Creates a key pair for `alias` if it does not exist.
150
+ - Defaults: `requireAuthentication = false`, `authMethod = PASSCODE_OR_BIOMETRIC`.
151
+
152
+ - `getPublicKey(alias: string, options?: GetPublicKeyOptions): string | null`
153
+ - Returns public key in PEM format (or `null` if alias not found).
154
+ - Defaults: `format = "PEM"`.
155
+
156
+ - `removeKeyPair(alias: string): boolean`
157
+ - Removes the key pair for the alias.
158
+
159
+ - `aliases(): string[]`
160
+ - Lists stored key aliases.
161
+
162
+ - `sign(alias: string, data: string, options?: SignOptions): Promise<string | null>`
163
+ - Signs UTF-8 `data` with private key.
164
+ - Defaults: `algorithmType = ECDSA_SECP256R1_SHA256`, `promptTitle = "Unlock"`, `promptSubtitle = "Enter your PIN to continue"`, `authMethod = PASSCODE_OR_BIOMETRIC`.
165
+
166
+ - `verify(alias: string, data: string, signature: string, options?: VerifyOptions): Promise<boolean | null>`
167
+ - Verifies signature for UTF-8 `data`.
168
+ - Signature must be in Base64 format.
169
+ - Default: `algorithmType = ECDSA_SECP256R1_SHA256`.
170
+
171
+ - `encrypt(alias: string, data: string, options?: EncryptOptions): Promise<string | null>`
172
+ - Encrypts UTF-8 `data` with public key.
173
+ - Default: `algorithmType = RSA_2048_PKCS1`.
174
+
175
+ - `decrypt(alias: string, data: string, options?: DecryptOptions): Promise<string | null>`
176
+ - Decrypts Base64 `data` with private key.
177
+ - Defaults: `algorithmType = RSA_2048_PKCS1`, `promptTitle = "Unlock"`, `promptSubtitle = "Enter your PIN to continue"`, `authMethod = PASSCODE_OR_BIOMETRIC`.
178
+
179
+ > ✅ JSDoc type definitions are available in `./src/DeviceCryptoModule.ts`.
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'expo.modules.devicecrypto'
4
- version = '0.1.0'
4
+ version = '0.2.0'
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.1.0"
38
+ versionName "0.2.0"
39
39
  }
40
40
  lintOptions {
41
41
  abortOnError false
@@ -1,26 +1,41 @@
1
1
  package expo.modules.devicecrypto
2
2
 
3
+ import android.content.Context
3
4
  import android.content.pm.PackageManager
4
5
  import android.security.keystore.KeyGenParameterSpec
5
6
  import android.security.keystore.KeyInfo
6
- import android.security.keystore.KeyProperties
7
- import expo.modules.kotlin.modules.Module
8
- import expo.modules.kotlin.modules.ModuleDefinition
9
- import java.security.KeyPairGenerator
10
- import java.security.KeyStore
7
+ import android.security.keystore.KeyProperties.AUTH_BIOMETRIC_STRONG
8
+ import android.security.keystore.KeyProperties.AUTH_DEVICE_CREDENTIAL
9
+ import android.security.keystore.KeyProperties.DIGEST_SHA1
10
+ import android.security.keystore.KeyProperties.DIGEST_SHA256
11
+ import android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_OAEP
12
+ import android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1
13
+ import android.security.keystore.KeyProperties.KEY_ALGORITHM_EC
14
+ import android.security.keystore.KeyProperties.KEY_ALGORITHM_RSA
15
+ import android.security.keystore.KeyProperties.PURPOSE_DECRYPT
16
+ import android.security.keystore.KeyProperties.PURPOSE_ENCRYPT
17
+ import android.security.keystore.KeyProperties.PURPOSE_SIGN
18
+ import android.security.keystore.KeyProperties.PURPOSE_VERIFY
11
19
  import android.util.Base64
12
20
  import androidx.biometric.BiometricManager
13
- import androidx.biometric.BiometricPrompt
14
21
  import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
15
22
  import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
23
+ import androidx.biometric.BiometricPrompt
16
24
  import androidx.core.content.ContextCompat
17
25
  import androidx.fragment.app.FragmentActivity
18
26
  import expo.modules.kotlin.Promise
19
- import java.security.Signature
20
- import android.widget.Toast
21
- import android.content.Context
27
+ import expo.modules.kotlin.modules.Module
28
+ import expo.modules.kotlin.modules.ModuleDefinition
22
29
  import java.security.KeyFactory
30
+ import java.security.KeyPairGenerator
31
+ import java.security.KeyStore
32
+ import java.security.Signature
33
+ import java.security.spec.AlgorithmParameterSpec
34
+ import java.security.spec.MGF1ParameterSpec
23
35
  import javax.crypto.Cipher
36
+ import javax.crypto.spec.OAEPParameterSpec
37
+ import javax.crypto.spec.PSource
38
+
24
39
 
25
40
  enum class GenerateKeyPairResult {
26
41
  KEY_PAIR_GENERATED,
@@ -42,6 +57,7 @@ enum class AuthMethod {
42
57
  enum class AlgorithmType {
43
58
  ECDSA_SECP256R1_SHA256,
44
59
  RSA_2048_PKCS1,
60
+ RSA_2048_OAEP_SHA1,
45
61
  }
46
62
 
47
63
  class DeviceCryptoModule : Module() {
@@ -49,6 +65,19 @@ class DeviceCryptoModule : Module() {
49
65
  return when (algorithm) {
50
66
  AlgorithmType.ECDSA_SECP256R1_SHA256 -> "SHA256withECDSA"
51
67
  AlgorithmType.RSA_2048_PKCS1 -> "RSA/ECB/PKCS1Padding"
68
+ AlgorithmType.RSA_2048_OAEP_SHA1 -> "RSA/ECB/OAEPwithSHA-1AndMGF1Padding"
69
+ }
70
+ }
71
+
72
+ private fun getOaepSpec(algoType: AlgorithmType): AlgorithmParameterSpec? {
73
+ return when (algoType) {
74
+ AlgorithmType.RSA_2048_OAEP_SHA1 -> OAEPParameterSpec(
75
+ "SHA-1",
76
+ "MGF1",
77
+ MGF1ParameterSpec.SHA1,
78
+ PSource.PSpecified.DEFAULT
79
+ )
80
+ else -> null
52
81
  }
53
82
  }
54
83
 
@@ -108,23 +137,26 @@ class DeviceCryptoModule : Module() {
108
137
  return true
109
138
  }
110
139
 
111
- private fun buildECDSA_SECP256R1_SHA256(alias: String, reqAuth: Boolean): KeyPairGenerator {
140
+ private fun buildECDSA(
141
+ alias: String,
142
+ digest: String,
143
+ reqAuth: Boolean): KeyPairGenerator {
112
144
  val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
113
- KeyProperties.KEY_ALGORITHM_EC,
145
+ KEY_ALGORITHM_EC,
114
146
  "AndroidKeyStore"
115
147
  )
116
148
 
117
149
  val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(
118
150
  alias,
119
- KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
151
+ PURPOSE_SIGN or PURPOSE_VERIFY
120
152
  ).run {
121
- setDigests(KeyProperties.DIGEST_SHA256)
153
+ setDigests(digest)
122
154
  setIsStrongBoxBacked(false) // TODO: Prefer strong box if available
123
155
  setUserAuthenticationRequired(reqAuth)
124
156
  if (reqAuth) {
125
157
  setUserAuthenticationParameters(
126
158
  30, // 30 seconds
127
- KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL
159
+ AUTH_BIOMETRIC_STRONG or AUTH_DEVICE_CREDENTIAL
128
160
  )
129
161
  }
130
162
  build()
@@ -133,23 +165,30 @@ class DeviceCryptoModule : Module() {
133
165
  return kpg
134
166
  }
135
167
 
136
- private fun buildRSA_2048_PKCS1(alias: String, reqAuth: Boolean): KeyPairGenerator {
168
+ private fun buildRSA(
169
+ alias: String,
170
+ digest: String?,
171
+ padding: String,
172
+ reqAuth: Boolean): KeyPairGenerator {
137
173
  val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
138
- KeyProperties.KEY_ALGORITHM_RSA,
174
+ KEY_ALGORITHM_RSA,
139
175
  "AndroidKeyStore"
140
176
  )
141
177
 
142
178
  val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(
143
179
  alias,
144
- KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
180
+ PURPOSE_ENCRYPT or PURPOSE_DECRYPT
145
181
  ).run {
146
- setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
182
+ if (digest != null) {
183
+ setDigests(digest)
184
+ }
185
+ setEncryptionPaddings(padding)
147
186
  setIsStrongBoxBacked(false) // TODO: Prefer strong box if available
148
187
  setUserAuthenticationRequired(reqAuth)
149
188
  if (reqAuth) {
150
189
  setUserAuthenticationParameters(
151
190
  30, // 30 seconds
152
- KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL
191
+ AUTH_BIOMETRIC_STRONG or AUTH_DEVICE_CREDENTIAL
153
192
  )
154
193
  }
155
194
  build()
@@ -200,8 +239,8 @@ class DeviceCryptoModule : Module() {
200
239
  .setSubtitle(subtitle)
201
240
  .setAllowedAuthenticators(
202
241
  when (authMethod) {
203
- AuthMethod.PASSCODE -> BiometricManager.Authenticators.DEVICE_CREDENTIAL
204
- AuthMethod.PASSCODE_OR_BIOMETRIC -> BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL
242
+ AuthMethod.PASSCODE -> DEVICE_CREDENTIAL
243
+ AuthMethod.PASSCODE_OR_BIOMETRIC -> BIOMETRIC_STRONG or DEVICE_CREDENTIAL
205
244
  }
206
245
  )
207
246
  .build()
@@ -231,8 +270,9 @@ class DeviceCryptoModule : Module() {
231
270
 
232
271
  val algoType = AlgorithmType.valueOf(o["algoType"] as String)
233
272
  val kpg = when (algoType) {
234
- AlgorithmType.ECDSA_SECP256R1_SHA256 -> buildECDSA_SECP256R1_SHA256(alias, reqAuth)
235
- AlgorithmType.RSA_2048_PKCS1 -> buildRSA_2048_PKCS1(alias, reqAuth)
273
+ AlgorithmType.ECDSA_SECP256R1_SHA256 -> buildECDSA(alias, DIGEST_SHA256, reqAuth)
274
+ AlgorithmType.RSA_2048_PKCS1 -> buildRSA(alias, null, ENCRYPTION_PADDING_RSA_PKCS1, reqAuth)
275
+ AlgorithmType.RSA_2048_OAEP_SHA1 -> buildRSA(alias, DIGEST_SHA1, ENCRYPTION_PADDING_RSA_OAEP, reqAuth)
236
276
  else -> throw Exception("INVALID_ALGORITHM_TYPE")
237
277
  }
238
278
 
@@ -328,9 +368,14 @@ class DeviceCryptoModule : Module() {
328
368
 
329
369
  val algoType = AlgorithmType.valueOf(o["algoType"] as String)
330
370
  val algo = toAndroidAlgo(algoType)
371
+ val oaepSpec = getOaepSpec(algoType)
331
372
 
332
373
  val cipher = Cipher.getInstance(algo)
333
- cipher.init(Cipher.ENCRYPT_MODE, entry.certificate.publicKey)
374
+ if (oaepSpec != null) {
375
+ cipher.init(Cipher.ENCRYPT_MODE, entry.certificate.publicKey, oaepSpec)
376
+ } else {
377
+ cipher.init(Cipher.ENCRYPT_MODE, entry.certificate.publicKey)
378
+ }
334
379
  val encrypted: ByteArray = cipher.doFinal(data.toByteArray(Charsets.UTF_8))
335
380
  promise.resolve(Base64.encodeToString(encrypted, Base64.NO_WRAP))
336
381
  }
@@ -352,19 +397,28 @@ class DeviceCryptoModule : Module() {
352
397
  val authMethod = o["authMethod"] as String
353
398
  val algoType = AlgorithmType.valueOf(o["algoType"] as String)
354
399
  val algo = toAndroidAlgo(algoType)
400
+ val oaepSpec = getOaepSpec(algoType)
355
401
 
356
402
  val cipher = Cipher.getInstance(algo)
357
403
  val ciphertext = Base64.decode(data, Base64.NO_WRAP)
358
404
 
359
405
  if (!reqAuth) {
360
- cipher.init(Cipher.DECRYPT_MODE, entry.privateKey)
406
+ if (oaepSpec != null) {
407
+ cipher.init(Cipher.DECRYPT_MODE, entry.privateKey, oaepSpec)
408
+ } else {
409
+ cipher.init(Cipher.DECRYPT_MODE, entry.privateKey)
410
+ }
361
411
  val decrypted: ByteArray = cipher.doFinal(ciphertext)
362
412
  promise.resolve(String(decrypted, Charsets.UTF_8))
363
413
  return@AsyncFunction
364
414
  } else {
365
415
  showAuthPrompt(
366
416
  onSuccess = {
367
- cipher.init(Cipher.DECRYPT_MODE, entry.privateKey)
417
+ if (oaepSpec != null) {
418
+ cipher.init(Cipher.DECRYPT_MODE, entry.privateKey, oaepSpec)
419
+ } else {
420
+ cipher.init(Cipher.DECRYPT_MODE, entry.privateKey)
421
+ }
368
422
  val decrypted: ByteArray = cipher.doFinal(ciphertext)
369
423
  promise.resolve(String(decrypted, Charsets.UTF_8))
370
424
  },
@@ -16,7 +16,8 @@ export declare enum SigningAlgorithm {
16
16
  ECDSA_SECP256R1_SHA256 = "ECDSA_SECP256R1_SHA256"
17
17
  }
18
18
  export declare enum EncryptionAlgorithm {
19
- RSA_2048_PKCS1 = "RSA_2048_PKCS1"
19
+ RSA_2048_PKCS1 = "RSA_2048_PKCS1",
20
+ RSA_2048_OAEP_SHA1 = "RSA_2048_OAEP_SHA1"
20
21
  }
21
22
  export interface GenerateKeyPairOptions {
22
23
  /**
@@ -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;CAClC;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;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"}
@@ -22,5 +22,6 @@ export var SigningAlgorithm;
22
22
  export var EncryptionAlgorithm;
23
23
  (function (EncryptionAlgorithm) {
24
24
  EncryptionAlgorithm["RSA_2048_PKCS1"] = "RSA_2048_PKCS1";
25
+ EncryptionAlgorithm["RSA_2048_OAEP_SHA1"] = "RSA_2048_OAEP_SHA1";
25
26
  })(EncryptionAlgorithm || (EncryptionAlgorithm = {}));
26
27
  //# sourceMappingURL=DeviceCrypto.types.js.map
@@ -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,mBAEX;AAFD,WAAY,mBAAmB;IAC7B,wDAAiC,CAAA;AACnC,CAAC,EAFW,mBAAmB,KAAnB,mBAAmB,QAE9B","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}\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\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"]}
@@ -46,8 +46,8 @@ declare const _default: {
46
46
  /**
47
47
  * Verifies the given data with the signature for the given alias.
48
48
  * @param alias - The alias to use for the key pair.
49
- * @param data - The data to verify.
50
- * @param signature - The signature to verify.
49
+ * @param data - The data to verify in UTF-8 format.
50
+ * @param signature - The signature to verify in Base64 format.
51
51
  * @param options - The options for the operation.
52
52
  * @default {
53
53
  * algoType: SigningAlgorithm.ECDSA_SHA256,
@@ -82,5 +82,4 @@ declare const _default: {
82
82
  decrypt: (alias: string, data: string, options?: DecryptOptions) => Promise<string | null>;
83
83
  };
84
84
  export default _default;
85
- export type { GenerateKeyPairResult };
86
85
  //# sourceMappingURL=DeviceCryptoModule.d.ts.map
@@ -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;AAEF,YAAY,EAAE,qBAAqB,EAAE,CAAC"}
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"}
@@ -76,8 +76,8 @@ export default {
76
76
  /**
77
77
  * Verifies the given data with the signature for the given alias.
78
78
  * @param alias - The alias to use for the key pair.
79
- * @param data - The data to verify.
80
- * @param signature - The signature to verify.
79
+ * @param data - The data to verify in UTF-8 format.
80
+ * @param signature - The signature to verify in Base64 format.
81
81
  * @param options - The options for the operation.
82
82
  * @default {
83
83
  * algoType: SigningAlgorithm.ECDSA_SHA256,
@@ -1 +1 @@
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 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.\n * @param signature - The signature to verify.\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};\n\nexport type { GenerateKeyPairResult };\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 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,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'DeviceCrypto'
3
- s.version = '0.1.0'
3
+ s.version = '0.2.0'
4
4
  s.summary = 'Device crypto'
5
5
  s.description = 'Device crypto for Expo using device hardware capabilities'
6
6
  s.author = 'Piotr Pietras'
@@ -23,6 +23,7 @@ enum AuthMethod: String {
23
23
  enum AlgorithmType: String {
24
24
  case ECDSA_SECP256R1_SHA256 = "ECDSA_SECP256R1_SHA256"
25
25
  case RSA_2048_PKCS1 = "RSA_2048_PKCS1"
26
+ case RSA_2048_OAEP_SHA1 = "RSA_2048_OAEP_SHA1"
26
27
  }
27
28
 
28
29
  public class DeviceCryptoModule: Module {
@@ -32,6 +33,8 @@ public class DeviceCryptoModule: Module {
32
33
  return .ecdsaSignatureMessageX962SHA256
33
34
  case .RSA_2048_PKCS1:
34
35
  return .rsaEncryptionPKCS1
36
+ case .RSA_2048_OAEP_SHA1:
37
+ return .rsaEncryptionOAEPSHA1
35
38
  }
36
39
  }
37
40
 
@@ -186,7 +189,7 @@ public class DeviceCryptoModule: Module {
186
189
  return privateStatus == errSecSuccess || publicStatus == errSecSuccess
187
190
  }
188
191
 
189
- private func buildECDSA_SECP256R1_SHA256(alias: String, reqAuth: Bool, authMethod: AuthMethod) -> SecKey? {
192
+ private func buildECDSA(alias: String, reqAuth: Bool, authMethod: AuthMethod) -> SecKey? {
190
193
  let accessFlags: SecAccessControlCreateFlags
191
194
  if reqAuth {
192
195
  switch authMethod {
@@ -224,7 +227,7 @@ public class DeviceCryptoModule: Module {
224
227
  return SecKeyCreateRandomKey(attributes, nil)
225
228
  }
226
229
 
227
- private func buildRSA_2048_PKCS1(alias: String, reqAuth: Bool, authMethod: AuthMethod) -> SecKey? {
230
+ private func buildRSA(alias: String, reqAuth: Bool, authMethod: AuthMethod) -> SecKey? {
228
231
  let accessFlags: SecAccessControlCreateFlags
229
232
  if reqAuth {
230
233
  switch authMethod {
@@ -289,9 +292,11 @@ public class DeviceCryptoModule: Module {
289
292
 
290
293
  switch algoType {
291
294
  case .ECDSA_SECP256R1_SHA256:
292
- self.buildECDSA_SECP256R1_SHA256(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
295
+ self.buildECDSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
293
296
  case .RSA_2048_PKCS1:
294
- self.buildRSA_2048_PKCS1(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
297
+ self.buildRSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
298
+ case .RSA_2048_OAEP_SHA1:
299
+ self.buildRSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
295
300
  default:
296
301
  throw NSError(
297
302
  domain: "DeviceCrypto",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-device-crypto",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Crypto for Expo using device hardware capabilities",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -21,6 +21,7 @@ export enum SigningAlgorithm {
21
21
 
22
22
  export enum EncryptionAlgorithm {
23
23
  RSA_2048_PKCS1 = "RSA_2048_PKCS1",
24
+ RSA_2048_OAEP_SHA1 = "RSA_2048_OAEP_SHA1",
24
25
  }
25
26
 
26
27
  export interface GenerateKeyPairOptions {
@@ -109,8 +109,8 @@ export default {
109
109
  /**
110
110
  * Verifies the given data with the signature for the given alias.
111
111
  * @param alias - The alias to use for the key pair.
112
- * @param data - The data to verify.
113
- * @param signature - The signature to verify.
112
+ * @param data - The data to verify in UTF-8 format.
113
+ * @param signature - The signature to verify in Base64 format.
114
114
  * @param options - The options for the operation.
115
115
  * @default {
116
116
  * algoType: SigningAlgorithm.ECDSA_SHA256,
@@ -166,6 +166,4 @@ export default {
166
166
  };
167
167
  return module.decrypt(alias, data, o);
168
168
  },
169
- };
170
-
171
- export type { GenerateKeyPairResult };
169
+ };