expo-device-crypto 0.1.1 → 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](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 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
 
@@ -42,6 +42,12 @@ If you want to allow Face ID on iOS, add this to your app config:
42
42
  **Padding:** PKCS#1 v1.5. </br>
43
43
  **Use it for:** Encrypting small secrets that only the private key holder should decrypt.
44
44
 
45
+ - #### `RSA_2048_OAEP_SHA1`
46
+
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.
50
+
45
51
  More coming soon
46
52
 
47
53
  ## Example: ECDSA with Biometric
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'expo.modules.devicecrypto'
4
- version = '0.1.1'
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.1"
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"]}
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'DeviceCrypto'
3
- s.version = '0.1.1'
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'
@@ -34,7 +34,7 @@ public class DeviceCryptoModule: Module {
34
34
  case .RSA_2048_PKCS1:
35
35
  return .rsaEncryptionPKCS1
36
36
  case .RSA_2048_OAEP_SHA1:
37
- return .rsaEncryptionOAEP
37
+ return .rsaEncryptionOAEPSHA1
38
38
  }
39
39
  }
40
40
 
@@ -295,6 +295,8 @@ public class DeviceCryptoModule: Module {
295
295
  self.buildECDSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
296
296
  case .RSA_2048_PKCS1:
297
297
  self.buildRSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
298
+ case .RSA_2048_OAEP_SHA1:
299
+ self.buildRSA(alias: alias, reqAuth: reqAuth, authMethod: authMethod!)
298
300
  default:
299
301
  throw NSError(
300
302
  domain: "DeviceCrypto",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-device-crypto",
3
- "version": "0.1.1",
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 {