@expo/app-integrity 0.1.7 → 0.1.8

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/integrity/IntegrityErrorCodes.kt +4 -0
  4. package/android/src/main/java/expo/modules/integrity/IntegrityModule.kt +101 -0
  5. package/build/AppIntegrity.d.ts +23 -0
  6. package/build/AppIntegrity.d.ts.map +1 -1
  7. package/build/AppIntegrity.js +38 -0
  8. package/build/AppIntegrity.js.map +1 -1
  9. package/build/ExpoAppIntegrity.types.d.ts +3 -0
  10. package/build/ExpoAppIntegrity.types.d.ts.map +1 -1
  11. package/build/ExpoAppIntegrity.types.js.map +1 -1
  12. package/expo-module.config.json +1 -1
  13. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8-sources.jar +0 -0
  14. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8-sources.jar.md5 +1 -0
  15. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8-sources.jar.sha1 +1 -0
  16. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8-sources.jar.sha256 +1 -0
  17. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8-sources.jar.sha512 +1 -0
  18. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.aar +0 -0
  19. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.aar.md5 +1 -0
  20. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.aar.sha1 +1 -0
  21. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.aar.sha256 +1 -0
  22. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.aar.sha512 +1 -0
  23. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/{0.1.7/expo.modules.integrity-0.1.7.module → 0.1.8/expo.modules.integrity-0.1.8.module} +22 -22
  24. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.module.md5 +1 -0
  25. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.module.sha1 +1 -0
  26. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.module.sha256 +1 -0
  27. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.module.sha512 +1 -0
  28. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/{0.1.7/expo.modules.integrity-0.1.7.pom → 0.1.8/expo.modules.integrity-0.1.8.pom} +1 -1
  29. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.pom.md5 +1 -0
  30. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.pom.sha1 +1 -0
  31. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.pom.sha256 +1 -0
  32. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.8/expo.modules.integrity-0.1.8.pom.sha512 +1 -0
  33. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/maven-metadata.xml +4 -4
  34. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/maven-metadata.xml.md5 +1 -1
  35. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/maven-metadata.xml.sha1 +1 -1
  36. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/maven-metadata.xml.sha256 +1 -1
  37. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/maven-metadata.xml.sha512 +1 -1
  38. package/package.json +2 -2
  39. package/src/AppIntegrity.ts +41 -0
  40. package/src/ExpoAppIntegrity.types.ts +5 -1
  41. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7-sources.jar +0 -0
  42. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7-sources.jar.md5 +0 -1
  43. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7-sources.jar.sha1 +0 -1
  44. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7-sources.jar.sha256 +0 -1
  45. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7-sources.jar.sha512 +0 -1
  46. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.aar +0 -0
  47. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.aar.md5 +0 -1
  48. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.aar.sha1 +0 -1
  49. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.aar.sha256 +0 -1
  50. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.aar.sha512 +0 -1
  51. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.module.md5 +0 -1
  52. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.module.sha1 +0 -1
  53. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.module.sha256 +0 -1
  54. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.module.sha512 +0 -1
  55. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.pom.md5 +0 -1
  56. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.pom.sha1 +0 -1
  57. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.pom.sha256 +0 -1
  58. package/local-maven-repo/expo/modules/integrity/expo.modules.integrity/0.1.7/expo.modules.integrity-0.1.7.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.1.8 — 2025-09-22
14
+
15
+ ### 🎉 New features
16
+
17
+ - [Android] Add Android hardware attestation support. ([#39725](https://github.com/expo/expo/pull/39725) by [@nishan](https://github.com/intergalacticspacehighway))
18
+
13
19
  ## 0.1.7 — 2025-09-11
14
20
 
15
21
  ### 🐛 Bug fixes
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'expo.modules.integrity'
7
- version = '0.1.7'
7
+ version = '0.1.8'
8
8
 
9
9
  android {
10
10
  namespace 'expo.modules.integrity'
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName "0.1.7"
13
+ versionName "0.1.8"
14
14
  }
15
15
  }
16
16
 
@@ -22,4 +22,8 @@ object IntegrityErrorCodes {
22
22
  const val NOT_PREPARED = "ERR_APP_INTEGRITY_PROVIDER_NOT_PREPARED"
23
23
  const val DECODE_FAILED = "ERR_APP_INTEGRITY_DECODE_FAILED"
24
24
  const val UNKNOWN = "ERR_APP_INTEGRITY_UNKNOWN"
25
+ const val HARDWARE_ATTESTATION_NOT_SUPPORTED = "ERR_APP_INTEGRITY_HARDWARE_ATTESTATION_NOT_SUPPORTED"
26
+ const val HARDWARE_ATTESTATION_KEY_GENERATION_FAILED = "ERR_APP_INTEGRITY_HARDWARE_ATTESTATION_KEY_GENERATION_FAILED"
27
+ const val HARDWARE_ATTESTATION_FAILED = "ERR_APP_INTEGRITY_HARDWARE_ATTESTATION_FAILED"
28
+ const val HARDWARE_ATTESTATION_CERTIFICATE_CHAIN_INVALID = "ERR_APP_INTEGRITY_HARDWARE_ATTESTATION_CERTIFICATE_CHAIN_INVALID"
25
29
  }
@@ -1,5 +1,9 @@
1
1
  package expo.modules.integrity
2
2
 
3
+ import android.os.Build
4
+ import android.security.keystore.KeyGenParameterSpec
5
+ import android.security.keystore.KeyProperties
6
+ import android.util.Base64
3
7
  import com.google.android.gms.tasks.Task
4
8
  import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityToken
5
9
  import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityTokenRequest
@@ -11,6 +15,9 @@ import expo.modules.kotlin.modules.Module
11
15
  import expo.modules.kotlin.modules.ModuleDefinition
12
16
  import expo.modules.kotlin.Promise
13
17
  import com.google.android.play.core.integrity.StandardIntegrityManager.PrepareIntegrityTokenRequest
18
+ import java.security.KeyPairGenerator
19
+ import java.security.KeyStore
20
+ import java.security.cert.X509Certificate
14
21
 
15
22
  class IntegrityModule : Module() {
16
23
  private var integrityTokenProvider: StandardIntegrityManager.StandardIntegrityTokenProvider? =
@@ -20,6 +27,7 @@ class IntegrityModule : Module() {
20
27
  companion object {
21
28
  private const val PREPARE_INTEGRITY_TOKEN_PROVIDER_METHOD_NAME = "prepareIntegrityTokenProvider"
22
29
  private const val REQUEST_INTEGRITY_CHECK_METHOD_NAME = "requestIntegrityCheck"
30
+ private const val ANDROID_KEYSTORE = "AndroidKeyStore"
23
31
  }
24
32
 
25
33
  override fun definition() = ModuleDefinition {
@@ -86,6 +94,30 @@ class IntegrityModule : Module() {
86
94
  }
87
95
  )
88
96
  }
97
+
98
+ AsyncFunction("isHardwareAttestationSupported") {
99
+ try {
100
+ isHardwareAttestationSupported()
101
+ } catch (e: Exception) {
102
+ throw IntegrityException(IntegrityErrorCodes.HARDWARE_ATTESTATION_NOT_SUPPORTED, e.message ?: "Failed to check hardware attestation support", e)
103
+ }
104
+ }
105
+
106
+ AsyncFunction("generateHardwareAttestedKey") { keyAlias: String, challenge: String ->
107
+ try {
108
+ generateHardwareAttestedKey(keyAlias, challenge)
109
+ } catch (e: Exception) {
110
+ throw handleHardwareAttestationError(e)
111
+ }
112
+ }
113
+
114
+ AsyncFunction("getAttestationCertificateChain") { keyAlias: String ->
115
+ try {
116
+ getAttestationCertificateChain(keyAlias)
117
+ } catch (e: Exception) {
118
+ throw handleHardwareAttestationError(e)
119
+ }
120
+ }
89
121
  }
90
122
 
91
123
  private fun handleIntegrityError(exception: Throwable?): IntegrityException {
@@ -129,4 +161,73 @@ class IntegrityModule : Module() {
129
161
  else -> IntegrityErrorCodes.UNKNOWN
130
162
  }
131
163
  }
164
+
165
+ private fun handleHardwareAttestationError(exception: Throwable): IntegrityException {
166
+ return when {
167
+ exception.message?.contains("not supported", ignoreCase = true) == true ->
168
+ IntegrityException(IntegrityErrorCodes.HARDWARE_ATTESTATION_NOT_SUPPORTED, exception.message ?: "Hardware attestation not supported", exception)
169
+ exception.message?.contains("key generation", ignoreCase = true) == true ->
170
+ IntegrityException(IntegrityErrorCodes.HARDWARE_ATTESTATION_KEY_GENERATION_FAILED, exception.message ?: "Key generation failed", exception)
171
+ exception.message?.contains("certificate", ignoreCase = true) == true ->
172
+ IntegrityException(IntegrityErrorCodes.HARDWARE_ATTESTATION_CERTIFICATE_CHAIN_INVALID, exception.message ?: "Certificate chain invalid", exception)
173
+ else -> IntegrityException(IntegrityErrorCodes.HARDWARE_ATTESTATION_FAILED, exception.message ?: "Hardware attestation failed", exception)
174
+ }
175
+ }
176
+
177
+ private fun isHardwareAttestationSupported(): Boolean {
178
+ return try {
179
+ // Verify we can actually access the hardware keystore
180
+ val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
181
+ keyStore.load(null)
182
+ true
183
+ } catch (e: Exception) {
184
+ throw e
185
+ }
186
+ }
187
+
188
+ private fun generateHardwareAttestedKey(keyAlias: String, challenge: String) {
189
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
190
+ throw Exception("Hardware attestation is not supported on this Android version.")
191
+ }
192
+ try {
193
+ val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
194
+ keyStore.load(null)
195
+
196
+ if (keyStore.containsAlias(keyAlias)) {
197
+ keyStore.deleteEntry(keyAlias)
198
+ }
199
+
200
+ val keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE)
201
+
202
+ val keyGenParameterSpec = KeyGenParameterSpec.Builder(
203
+ keyAlias,
204
+ KeyProperties.PURPOSE_SIGN
205
+ )
206
+ .setDigests(KeyProperties.DIGEST_SHA256)
207
+ .setAttestationChallenge(challenge.toByteArray())
208
+ .build()
209
+
210
+ keyPairGenerator.initialize(keyGenParameterSpec)
211
+ keyPairGenerator.generateKeyPair()
212
+ } catch (e: Exception) {
213
+ throw Exception("Failed to generate hardware-attested key: ${e.message}", e)
214
+ }
215
+ }
216
+
217
+ private fun getAttestationCertificateChain(keyAlias: String): List<String> {
218
+ try {
219
+ val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
220
+ keyStore.load(null)
221
+
222
+ val certificateChain = keyStore.getCertificateChain(keyAlias)
223
+ ?: throw Exception("No certificate chain found for key alias: $keyAlias")
224
+
225
+ return certificateChain.map { certificate ->
226
+ val x509Certificate = certificate as X509Certificate
227
+ Base64.encodeToString(x509Certificate.encoded, Base64.NO_WRAP)
228
+ }
229
+ } catch (e: Exception) {
230
+ throw Exception("Failed to get certificate chain: ${e.message}", e)
231
+ }
232
+ }
132
233
  }
@@ -40,4 +40,27 @@ export declare function prepareIntegrityTokenProvider(cloudProjectNumber: string
40
40
  * @platform android
41
41
  */
42
42
  export declare function requestIntegrityCheck(requestHash: string): Promise<string>;
43
+ /**
44
+ * Checks if hardware attestation is supported on this device.
45
+ * @return A Promise that is fulfilled with a boolean indicating support.
46
+ * @platform android
47
+ */
48
+ export declare function isHardwareAttestationSupported(): Promise<boolean>;
49
+ /**
50
+ * Generates a hardware-attested key pair in the Android Keystore.
51
+ * This key can be used for attestation on GrapheneOS and other secure Android distributions.
52
+ * @param keyAlias A unique identifier for the key.
53
+ * @param challenge A challenge string from your server.
54
+ * @return A Promise that resolves when the key is generated successfully.
55
+ * @platform android
56
+ */
57
+ export declare function generateHardwareAttestedKey(keyAlias: string, challenge: string): Promise<void>;
58
+ /**
59
+ * Retrieves the attestation certificate chain for a hardware-attested key.
60
+ * The certificate chain can be validated on your server to verify device integrity.
61
+ * @param keyAlias The identifier of the key to get certificates for.
62
+ * @return A Promise that is fulfilled with an array of base64-encoded X.509 certificates.
63
+ * @platform android
64
+ */
65
+ export declare function getAttestationCertificateChain(keyAlias: string): Promise<string[]>;
43
66
  //# sourceMappingURL=AppIntegrity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppIntegrity.d.ts","sourceRoot":"","sources":["../src/AppIntegrity.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,WAAW,SAA8D,CAAC;AAEvF;;;;GAIG;AACH,wBAAsB,WAAW,oBAKhC;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAK/D;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAKvE;AAED;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,kBAAkB,EAAE,MAAM,iBAK7E;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,mBAK9D"}
1
+ {"version":3,"file":"AppIntegrity.d.ts","sourceRoot":"","sources":["../src/AppIntegrity.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,WAAW,SAA8D,CAAC;AAEvF;;;;GAIG;AACH,wBAAsB,WAAW,oBAKhC;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAK/D;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAKvE;AAED;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,kBAAkB,EAAE,MAAM,iBAK7E;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,mBAK9D;AAED;;;;GAIG;AACH,wBAAsB,8BAA8B,qBAKnD;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAKpF;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,qBAKpE"}
@@ -67,4 +67,42 @@ export async function requestIntegrityCheck(requestHash) {
67
67
  }
68
68
  return ExpoAppIntegrity.requestIntegrityCheck(requestHash);
69
69
  }
70
+ /**
71
+ * Checks if hardware attestation is supported on this device.
72
+ * @return A Promise that is fulfilled with a boolean indicating support.
73
+ * @platform android
74
+ */
75
+ export async function isHardwareAttestationSupported() {
76
+ if (Platform.OS !== 'android') {
77
+ return false;
78
+ }
79
+ return ExpoAppIntegrity.isHardwareAttestationSupported();
80
+ }
81
+ /**
82
+ * Generates a hardware-attested key pair in the Android Keystore.
83
+ * This key can be used for attestation on GrapheneOS and other secure Android distributions.
84
+ * @param keyAlias A unique identifier for the key.
85
+ * @param challenge A challenge string from your server.
86
+ * @return A Promise that resolves when the key is generated successfully.
87
+ * @platform android
88
+ */
89
+ export async function generateHardwareAttestedKey(keyAlias, challenge) {
90
+ if (Platform.OS !== 'android') {
91
+ throw new Error('generateHardwareAttestedKey is only available on Android');
92
+ }
93
+ return ExpoAppIntegrity.generateHardwareAttestedKey(keyAlias, challenge);
94
+ }
95
+ /**
96
+ * Retrieves the attestation certificate chain for a hardware-attested key.
97
+ * The certificate chain can be validated on your server to verify device integrity.
98
+ * @param keyAlias The identifier of the key to get certificates for.
99
+ * @return A Promise that is fulfilled with an array of base64-encoded X.509 certificates.
100
+ * @platform android
101
+ */
102
+ export async function getAttestationCertificateChain(keyAlias) {
103
+ if (Platform.OS !== 'android') {
104
+ throw new Error('getAttestationCertificateChain is only available on Android');
105
+ }
106
+ return ExpoAppIntegrity.getAttestationCertificateChain(keyAlias);
107
+ }
70
108
  //# sourceMappingURL=AppIntegrity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppIntegrity.js","sourceRoot":"","sources":["../src/AppIntegrity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAEvF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,SAAiB;IAC9D,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,SAAiB;IACtE,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,kBAA0B;IAC5E,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,gBAAgB,CAAC,6BAA6B,CAAC,kBAAkB,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB;IAC7D,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,gBAAgB,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["import { Platform } from 'react-native';\n\nimport ExpoAppIntegrity from './ExpoAppIntegrity';\n\n/**\n * A boolean value that indicates whether a particular device provides the [App Attest](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity) service.\n * Not all device types support the App Attest service, so check for support before using the service.\n * @platform ios\n */\nexport const isSupported = Platform.OS === 'ios' ? ExpoAppIntegrity.isSupported : true;\n\n/**\n * Creates a new cryptographic key for use with the App Attest service.\n * @return A Promise that is fulfilled with a string that contains the key identifier. The key itself is stored securely in the Secure Enclave.\n * @platform ios\n */\nexport async function generateKey() {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.generateKey();\n}\n\n/**\n * Asks Apple to attest to the validity of a generated cryptographic key.\n * @param keyId The identifier you received by calling the `generateKey` function.\n * @param challenge A challenge string from your server.\n * @return A Promise that is fulfilled with a string that contains the attestation data. A statement from Apple about the validity of the key associated with keyId. Send this to your server for processing.\n * @platform ios\n */\nexport async function attestKey(keyId: string, challenge: string) {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.attestKey(keyId, challenge);\n}\n\n/**\n * Creates a block of data that demonstrates the legitimacy of an instance of your app running on a device.\n * @param keyId The identifier you received by calling the `generateKey` function.\n * @param challenge A string to be signed with the attested private key.\n * @return A Promise that is fulfilled with a string that contains the assertion object. A data structure that you send to your server for processing.\n * @platform ios\n */\nexport async function generateAssertion(keyId: string, challenge: string) {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.generateAssertion(keyId, challenge);\n}\n\n/**\n * Prepares the integrity token provider for the given cloud project number.\n * @param cloudProjectNumber The cloud project number.\n * @return A Promise that is fulfilled if the integrity token provider is prepared successfully.\n * @platform android\n */\nexport async function prepareIntegrityTokenProvider(cloudProjectNumber: string) {\n if (Platform.OS !== 'android') {\n throw new Error('prepareIntegrityTokenProvider is only available on Android');\n }\n return ExpoAppIntegrity.prepareIntegrityTokenProvider(cloudProjectNumber);\n}\n\n/**\n * Requests an integrity verdict for the given request hash from Google Play.\n * @param requestHash A string representing the request hash.\n * @return A Promise that is fulfilled with a string that contains the integrity check result.\n * @platform android\n */\nexport async function requestIntegrityCheck(requestHash: string) {\n if (Platform.OS !== 'android') {\n throw new Error('requestIntegrityCheck is only available on Android');\n }\n return ExpoAppIntegrity.requestIntegrityCheck(requestHash);\n}\n"]}
1
+ {"version":3,"file":"AppIntegrity.js","sourceRoot":"","sources":["../src/AppIntegrity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAEvF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,SAAiB;IAC9D,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,SAAiB;IACtE,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,kBAA0B;IAC5E,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,gBAAgB,CAAC,6BAA6B,CAAC,kBAAkB,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB;IAC7D,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,gBAAgB,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,gBAAgB,CAAC,8BAA8B,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,QAAgB,EAAE,SAAiB;IACnF,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,gBAAgB,CAAC,2BAA2B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,QAAgB;IACnE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,gBAAgB,CAAC,8BAA8B,CAAC,QAAQ,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { Platform } from 'react-native';\n\nimport ExpoAppIntegrity from './ExpoAppIntegrity';\n\n/**\n * A boolean value that indicates whether a particular device provides the [App Attest](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity) service.\n * Not all device types support the App Attest service, so check for support before using the service.\n * @platform ios\n */\nexport const isSupported = Platform.OS === 'ios' ? ExpoAppIntegrity.isSupported : true;\n\n/**\n * Creates a new cryptographic key for use with the App Attest service.\n * @return A Promise that is fulfilled with a string that contains the key identifier. The key itself is stored securely in the Secure Enclave.\n * @platform ios\n */\nexport async function generateKey() {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.generateKey();\n}\n\n/**\n * Asks Apple to attest to the validity of a generated cryptographic key.\n * @param keyId The identifier you received by calling the `generateKey` function.\n * @param challenge A challenge string from your server.\n * @return A Promise that is fulfilled with a string that contains the attestation data. A statement from Apple about the validity of the key associated with keyId. Send this to your server for processing.\n * @platform ios\n */\nexport async function attestKey(keyId: string, challenge: string) {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.attestKey(keyId, challenge);\n}\n\n/**\n * Creates a block of data that demonstrates the legitimacy of an instance of your app running on a device.\n * @param keyId The identifier you received by calling the `generateKey` function.\n * @param challenge A string to be signed with the attested private key.\n * @return A Promise that is fulfilled with a string that contains the assertion object. A data structure that you send to your server for processing.\n * @platform ios\n */\nexport async function generateAssertion(keyId: string, challenge: string) {\n if (Platform.OS !== 'ios') {\n throw new Error('generateAssertion is only available on iOS');\n }\n return ExpoAppIntegrity.generateAssertion(keyId, challenge);\n}\n\n/**\n * Prepares the integrity token provider for the given cloud project number.\n * @param cloudProjectNumber The cloud project number.\n * @return A Promise that is fulfilled if the integrity token provider is prepared successfully.\n * @platform android\n */\nexport async function prepareIntegrityTokenProvider(cloudProjectNumber: string) {\n if (Platform.OS !== 'android') {\n throw new Error('prepareIntegrityTokenProvider is only available on Android');\n }\n return ExpoAppIntegrity.prepareIntegrityTokenProvider(cloudProjectNumber);\n}\n\n/**\n * Requests an integrity verdict for the given request hash from Google Play.\n * @param requestHash A string representing the request hash.\n * @return A Promise that is fulfilled with a string that contains the integrity check result.\n * @platform android\n */\nexport async function requestIntegrityCheck(requestHash: string) {\n if (Platform.OS !== 'android') {\n throw new Error('requestIntegrityCheck is only available on Android');\n }\n return ExpoAppIntegrity.requestIntegrityCheck(requestHash);\n}\n\n/**\n * Checks if hardware attestation is supported on this device.\n * @return A Promise that is fulfilled with a boolean indicating support.\n * @platform android\n */\nexport async function isHardwareAttestationSupported() {\n if (Platform.OS !== 'android') {\n return false;\n }\n return ExpoAppIntegrity.isHardwareAttestationSupported();\n}\n\n/**\n * Generates a hardware-attested key pair in the Android Keystore.\n * This key can be used for attestation on GrapheneOS and other secure Android distributions.\n * @param keyAlias A unique identifier for the key.\n * @param challenge A challenge string from your server.\n * @return A Promise that resolves when the key is generated successfully.\n * @platform android\n */\nexport async function generateHardwareAttestedKey(keyAlias: string, challenge: string) {\n if (Platform.OS !== 'android') {\n throw new Error('generateHardwareAttestedKey is only available on Android');\n }\n return ExpoAppIntegrity.generateHardwareAttestedKey(keyAlias, challenge);\n}\n\n/**\n * Retrieves the attestation certificate chain for a hardware-attested key.\n * The certificate chain can be validated on your server to verify device integrity.\n * @param keyAlias The identifier of the key to get certificates for.\n * @return A Promise that is fulfilled with an array of base64-encoded X.509 certificates.\n * @platform android\n */\nexport async function getAttestationCertificateChain(keyAlias: string) {\n if (Platform.OS !== 'android') {\n throw new Error('getAttestationCertificateChain is only available on Android');\n }\n return ExpoAppIntegrity.getAttestationCertificateChain(keyAlias);\n}\n"]}
@@ -9,5 +9,8 @@ export interface ExpoAppIntegrityModule extends NativeModule {
9
9
  generateAssertion(keyId: string, challenge: string): Promise<string>;
10
10
  prepareIntegrityTokenProvider(cloudProjectNumber: string): Promise<void>;
11
11
  requestIntegrityCheck(requestHash: string): Promise<string>;
12
+ isHardwareAttestationSupported(): Promise<boolean>;
13
+ generateHardwareAttestedKey(keyAlias: string, challenge: string): Promise<void>;
14
+ getAttestationCertificateChain(keyAlias: string): Promise<string[]>;
12
15
  }
13
16
  //# sourceMappingURL=ExpoAppIntegrity.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAppIntegrity.types.d.ts","sourceRoot":"","sources":["../src/ExpoAppIntegrity.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAE1D,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAErE,6BAA6B,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7D"}
1
+ {"version":3,"file":"ExpoAppIntegrity.types.d.ts","sourceRoot":"","sources":["../src/ExpoAppIntegrity.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAE1D,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAErE,6BAA6B,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5D,8BAA8B,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAppIntegrity.types.js","sourceRoot":"","sources":["../src/ExpoAppIntegrity.types.ts"],"names":[],"mappings":"","sourcesContent":["import { NativeModule } from 'expo-modules-core/types';\n\n/**\n * @hidden\n */\nexport interface ExpoAppIntegrityModule extends NativeModule {\n // iOS\n isSupported: boolean;\n generateKey(): Promise<string>;\n attestKey(keyId: string, challenge: string): Promise<string>;\n generateAssertion(keyId: string, challenge: string): Promise<string>;\n // Android\n prepareIntegrityTokenProvider(cloudProjectNumber: string): Promise<void>;\n requestIntegrityCheck(requestHash: string): Promise<string>;\n}\n"]}
1
+ {"version":3,"file":"ExpoAppIntegrity.types.js","sourceRoot":"","sources":["../src/ExpoAppIntegrity.types.ts"],"names":[],"mappings":"","sourcesContent":["import { NativeModule } from 'expo-modules-core/types';\n\n/**\n * @hidden\n */\nexport interface ExpoAppIntegrityModule extends NativeModule {\n // iOS\n isSupported: boolean;\n generateKey(): Promise<string>;\n attestKey(keyId: string, challenge: string): Promise<string>;\n generateAssertion(keyId: string, challenge: string): Promise<string>;\n // Android - Play Integrity\n prepareIntegrityTokenProvider(cloudProjectNumber: string): Promise<void>;\n requestIntegrityCheck(requestHash: string): Promise<string>;\n // Android - Hardware Attestation\n isHardwareAttestationSupported(): Promise<boolean>;\n generateHardwareAttestedKey(keyAlias: string, challenge: string): Promise<void>;\n getAttestationCertificateChain(keyAlias: string): Promise<string[]>;\n}\n"]}
@@ -8,7 +8,7 @@
8
8
  "publication": {
9
9
  "groupId": "expo.modules.integrity",
10
10
  "artifactId": "expo.modules.integrity",
11
- "version": "0.1.7",
11
+ "version": "0.1.8",
12
12
  "repository": "local-maven-repo"
13
13
  }
14
14
  }
@@ -0,0 +1 @@
1
+ 4512f979829d433bf955ed04bb4f0014fa6c9987c978fe562db52c28f8dd7be9
@@ -0,0 +1 @@
1
+ 5e6df019863896ddafc74e3114f2466d769e0775de771210764692d8c577010695cdf5a38619c1a794c3956da11e075bc6ca96f20a7dacb5ceaefe4b5a8012d7
@@ -0,0 +1 @@
1
+ 4a28e10d4bcb28e2da698e3cc8802e533b44834a06fbdda7f20ff535e6dfb647
@@ -0,0 +1 @@
1
+ fca74a314c0a20e21ff5363776c85b2e33f616199820c6600f2a750eff749a15b5398da2e55fb8d314a0ae7b0d63c9c2353bbe031691d5544a573b724c207f39
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "expo.modules.integrity",
5
5
  "module": "expo.modules.integrity",
6
- "version": "0.1.7",
6
+ "version": "0.1.8",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.integrity-0.1.7.aar",
28
- "url": "expo.modules.integrity-0.1.7.aar",
29
- "size": 20823,
30
- "sha512": "0f4cf0eb749bce9e1385bff59258369ebca662007986e457d571a0bb6b8622b8a4ab2613d90988c50cce5ec448e0a8ee640b7df7b22d8161cb57437331c6ecde",
31
- "sha256": "7d66543f5aede006f25c4aa24efeeffcde047cefd67dd953e3685d771bc5496a",
32
- "sha1": "a96cd645ab0b10555782a08cce606a76e23b6140",
33
- "md5": "b5a97dd5a1bcb837ab8f5732e4d63b51"
27
+ "name": "expo.modules.integrity-0.1.8.aar",
28
+ "url": "expo.modules.integrity-0.1.8.aar",
29
+ "size": 31554,
30
+ "sha512": "fca74a314c0a20e21ff5363776c85b2e33f616199820c6600f2a750eff749a15b5398da2e55fb8d314a0ae7b0d63c9c2353bbe031691d5544a573b724c207f39",
31
+ "sha256": "4a28e10d4bcb28e2da698e3cc8802e533b44834a06fbdda7f20ff535e6dfb647",
32
+ "sha1": "b2a3cd60cb041d2cd7c82dbbefbe7d0b1e99de3a",
33
+ "md5": "81536bd1d244aedaf579b11d9568c935"
34
34
  }
35
35
  ]
36
36
  },
@@ -60,13 +60,13 @@
60
60
  ],
61
61
  "files": [
62
62
  {
63
- "name": "expo.modules.integrity-0.1.7.aar",
64
- "url": "expo.modules.integrity-0.1.7.aar",
65
- "size": 20823,
66
- "sha512": "0f4cf0eb749bce9e1385bff59258369ebca662007986e457d571a0bb6b8622b8a4ab2613d90988c50cce5ec448e0a8ee640b7df7b22d8161cb57437331c6ecde",
67
- "sha256": "7d66543f5aede006f25c4aa24efeeffcde047cefd67dd953e3685d771bc5496a",
68
- "sha1": "a96cd645ab0b10555782a08cce606a76e23b6140",
69
- "md5": "b5a97dd5a1bcb837ab8f5732e4d63b51"
63
+ "name": "expo.modules.integrity-0.1.8.aar",
64
+ "url": "expo.modules.integrity-0.1.8.aar",
65
+ "size": 31554,
66
+ "sha512": "fca74a314c0a20e21ff5363776c85b2e33f616199820c6600f2a750eff749a15b5398da2e55fb8d314a0ae7b0d63c9c2353bbe031691d5544a573b724c207f39",
67
+ "sha256": "4a28e10d4bcb28e2da698e3cc8802e533b44834a06fbdda7f20ff535e6dfb647",
68
+ "sha1": "b2a3cd60cb041d2cd7c82dbbefbe7d0b1e99de3a",
69
+ "md5": "81536bd1d244aedaf579b11d9568c935"
70
70
  }
71
71
  ]
72
72
  },
@@ -80,13 +80,13 @@
80
80
  },
81
81
  "files": [
82
82
  {
83
- "name": "expo.modules.integrity-0.1.7-sources.jar",
84
- "url": "expo.modules.integrity-0.1.7-sources.jar",
85
- "size": 3403,
86
- "sha512": "e7f267cc0787ef413c398cffe83b2370eeb304fa1f19dca189e903c71b1946926f9814b0aef36ff36d7c82436e95c5e26230c47a97fc2bf79b4b5146978fe663",
87
- "sha256": "9b7e44c18df40296e89ec111fd1093841c27a50d2dd6f9d8db9a0a7bf810eef7",
88
- "sha1": "41cda41cb0b43ddb0bea3c5b5b283490346a62dc",
89
- "md5": "594e9d7dac41e6c828b54d0afaf12267"
83
+ "name": "expo.modules.integrity-0.1.8-sources.jar",
84
+ "url": "expo.modules.integrity-0.1.8-sources.jar",
85
+ "size": 4420,
86
+ "sha512": "5e6df019863896ddafc74e3114f2466d769e0775de771210764692d8c577010695cdf5a38619c1a794c3956da11e075bc6ca96f20a7dacb5ceaefe4b5a8012d7",
87
+ "sha256": "4512f979829d433bf955ed04bb4f0014fa6c9987c978fe562db52c28f8dd7be9",
88
+ "sha1": "a2399da6fd22e38235efc0fef9964cf964c2281d",
89
+ "md5": "bd471f1dcf69cbbf5e0172fbeb373e6c"
90
90
  }
91
91
  ]
92
92
  }
@@ -0,0 +1 @@
1
+ b769157ae3f102be63f135c176224fbef92d00e5c2e755bbafeb6ca8d41b6fa8
@@ -0,0 +1 @@
1
+ 10d73c6fd4fe18bc36898aacab3b82b313010a68e8efc5bc20ef3604b47338eb3ae2da967a752f93a94e0ffad6255fc27c17817da047d43b9f29e0df3c065761
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>expo.modules.integrity</groupId>
11
11
  <artifactId>expo.modules.integrity</artifactId>
12
- <version>0.1.7</version>
12
+ <version>0.1.8</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.integrity</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ e3edba75a1e9dab1178485f97d3b02ecd91fc32f3fae50d28e9f1458dce4c037
@@ -0,0 +1 @@
1
+ 6061cc361102a13342f46463efe5c884e5a7ace3c8f260e025b6448670b1fb5f1f1c046f8ed15cd6de7e9f881ff7f60576e3b2c563bcd2e60c522b4ac2be5ea6
@@ -3,11 +3,11 @@
3
3
  <groupId>expo.modules.integrity</groupId>
4
4
  <artifactId>expo.modules.integrity</artifactId>
5
5
  <versioning>
6
- <latest>0.1.7</latest>
7
- <release>0.1.7</release>
6
+ <latest>0.1.8</latest>
7
+ <release>0.1.8</release>
8
8
  <versions>
9
- <version>0.1.7</version>
9
+ <version>0.1.8</version>
10
10
  </versions>
11
- <lastUpdated>20250911202149</lastUpdated>
11
+ <lastUpdated>20250922222655</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- d8e96b785261790c00c476772d97d33c
1
+ 4c3898dd0933ddd5314d2157e1cfb91b
@@ -1 +1 @@
1
- 27633613e44e18cf9cea66b187e575d52d5697da
1
+ 1b6363aa8512931d1055661ca7f18db4da34675b
@@ -1 +1 @@
1
- f0d80100a5fca156ec16dec707a157cad05ee47f6a3d1f1c85e257905aa6f452
1
+ e2bca5909006e51d4ef6db8943d091fbd2f0b864b62d53beac65682d29904379
@@ -1 +1 @@
1
- 8ee841503bb9bb1aa49651509dab1db6830f4df8c16a389a235a6bd62a7a3d0e2e08b70b9eb290cbda10db7c4ac7a643c3505562be57e0df1dd1af6698015c2d
1
+ 30693db782e032d466d29cff1bdf54ca1f08bf60cca1bc689f91b6ecc51bf5c09fab416a8456fd7cc8631068dba2233479a2090bbf8db4bcb40003e8209f814f
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/app-integrity",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A native module that helps assert app integrity on mobile platforms",
5
5
  "sideEffects": false,
6
6
  "main": "build/index.js",
@@ -43,5 +43,5 @@
43
43
  "expo": "*",
44
44
  "react-native": "*"
45
45
  },
46
- "gitHead": "088e79428be97cf3ee11fc93e0e5a1fc1c8bea1e"
46
+ "gitHead": "6523053d0d997d2a21f580d2752b2f873c122038"
47
47
  }
@@ -74,3 +74,44 @@ export async function requestIntegrityCheck(requestHash: string) {
74
74
  }
75
75
  return ExpoAppIntegrity.requestIntegrityCheck(requestHash);
76
76
  }
77
+
78
+ /**
79
+ * Checks if hardware attestation is supported on this device.
80
+ * @return A Promise that is fulfilled with a boolean indicating support.
81
+ * @platform android
82
+ */
83
+ export async function isHardwareAttestationSupported() {
84
+ if (Platform.OS !== 'android') {
85
+ return false;
86
+ }
87
+ return ExpoAppIntegrity.isHardwareAttestationSupported();
88
+ }
89
+
90
+ /**
91
+ * Generates a hardware-attested key pair in the Android Keystore.
92
+ * This key can be used for attestation on GrapheneOS and other secure Android distributions.
93
+ * @param keyAlias A unique identifier for the key.
94
+ * @param challenge A challenge string from your server.
95
+ * @return A Promise that resolves when the key is generated successfully.
96
+ * @platform android
97
+ */
98
+ export async function generateHardwareAttestedKey(keyAlias: string, challenge: string) {
99
+ if (Platform.OS !== 'android') {
100
+ throw new Error('generateHardwareAttestedKey is only available on Android');
101
+ }
102
+ return ExpoAppIntegrity.generateHardwareAttestedKey(keyAlias, challenge);
103
+ }
104
+
105
+ /**
106
+ * Retrieves the attestation certificate chain for a hardware-attested key.
107
+ * The certificate chain can be validated on your server to verify device integrity.
108
+ * @param keyAlias The identifier of the key to get certificates for.
109
+ * @return A Promise that is fulfilled with an array of base64-encoded X.509 certificates.
110
+ * @platform android
111
+ */
112
+ export async function getAttestationCertificateChain(keyAlias: string) {
113
+ if (Platform.OS !== 'android') {
114
+ throw new Error('getAttestationCertificateChain is only available on Android');
115
+ }
116
+ return ExpoAppIntegrity.getAttestationCertificateChain(keyAlias);
117
+ }
@@ -9,7 +9,11 @@ export interface ExpoAppIntegrityModule extends NativeModule {
9
9
  generateKey(): Promise<string>;
10
10
  attestKey(keyId: string, challenge: string): Promise<string>;
11
11
  generateAssertion(keyId: string, challenge: string): Promise<string>;
12
- // Android
12
+ // Android - Play Integrity
13
13
  prepareIntegrityTokenProvider(cloudProjectNumber: string): Promise<void>;
14
14
  requestIntegrityCheck(requestHash: string): Promise<string>;
15
+ // Android - Hardware Attestation
16
+ isHardwareAttestationSupported(): Promise<boolean>;
17
+ generateHardwareAttestedKey(keyAlias: string, challenge: string): Promise<void>;
18
+ getAttestationCertificateChain(keyAlias: string): Promise<string[]>;
15
19
  }
@@ -1 +0,0 @@
1
- 9b7e44c18df40296e89ec111fd1093841c27a50d2dd6f9d8db9a0a7bf810eef7
@@ -1 +0,0 @@
1
- e7f267cc0787ef413c398cffe83b2370eeb304fa1f19dca189e903c71b1946926f9814b0aef36ff36d7c82436e95c5e26230c47a97fc2bf79b4b5146978fe663
@@ -1 +0,0 @@
1
- 7d66543f5aede006f25c4aa24efeeffcde047cefd67dd953e3685d771bc5496a
@@ -1 +0,0 @@
1
- 0f4cf0eb749bce9e1385bff59258369ebca662007986e457d571a0bb6b8622b8a4ab2613d90988c50cce5ec448e0a8ee640b7df7b22d8161cb57437331c6ecde
@@ -1 +0,0 @@
1
- 8caac8e8b29812068266be62fc2cb287c3b0b1a97c64cd901944385ec60e8899
@@ -1 +0,0 @@
1
- bf5e188132d9014733c92b2bad43eb025c92696b3d218b3fb501b482046f325c7711cdaf5db089fc06c93bd5d76006e426c29bb318eee397d297819a46dc1df9
@@ -1 +0,0 @@
1
- 68200f2af56afa76fa0d9c19bc95dc8c209d4cc88a531df57cffa1d49988cef4
@@ -1 +0,0 @@
1
- 4dcbc1f9c15289ed6889f7c89cdc4353413554729662084c2abbe2efe0bc2a5b82222d5beadcc9a82eccbc4e913022a8684cc0a7e3a7d2bc49ad6ded885f617a