react-native-dpop 0.2.0 → 0.3.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 +11 -0
- package/android/src/main/java/com/reactnativedpop/DPoPKeyStore.kt +29 -0
- package/android/src/main/java/com/reactnativedpop/DPoPModule.kt +31 -5
- package/ios/DPoPKeyStore.swift +46 -11
- package/ios/DPoPModule.swift +24 -4
- package/ios/SecureEnclaveKeyStore.swift +15 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +15 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/index.tsx +16 -3
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ const isBound = await dpop.isBoundToAlias();
|
|
|
54
54
|
- `GenerateProofInput`
|
|
55
55
|
- `DPoPProofContext`
|
|
56
56
|
- `DPoPKeyInfo`
|
|
57
|
+
- `SecureHardwareFallbackReason = 'UNAVAILABLE' | 'PROVIDER_ERROR' | 'POLICY_REJECTED' | 'UNKNOWN'`
|
|
57
58
|
- `PublicJwk`
|
|
58
59
|
- `PublicKeyFormat = 'JWK' | 'DER' | 'RAW'`
|
|
59
60
|
|
|
@@ -97,6 +98,16 @@ Native errors are rejected with codes such as:
|
|
|
97
98
|
## Notes
|
|
98
99
|
|
|
99
100
|
- If no alias is provided, the default alias is `react-native-dpop`.
|
|
101
|
+
- `getKeyInfo` returns cross-platform fields and platform-specific details in `hardware`:
|
|
102
|
+
- Android: `hardware.android.strongBoxAvailable`, `hardware.android.strongBoxBacked`, `hardware.android.securityLevel`, `hardware.android.strongBoxFallbackReason`
|
|
103
|
+
- iOS: `hardware.ios.secureEnclaveAvailable`, `hardware.ios.secureEnclaveBacked`, `hardware.ios.securityLevel`, `hardware.ios.secureEnclaveFallbackReason`
|
|
104
|
+
- Fallback reasons are sanitized enums (no raw native error): `UNAVAILABLE`, `PROVIDER_ERROR`, `POLICY_REJECTED`, `UNKNOWN`.
|
|
105
|
+
- `securityLevel` semantics:
|
|
106
|
+
- `null`: no key material available (or not reported)
|
|
107
|
+
- `1`: not backed by secure enclave/strong dedicated hardware
|
|
108
|
+
- `2`: hardware-backed (iOS Secure Enclave, Android typically TEE)
|
|
109
|
+
- `3`: Android-only StrongBox (when reported by the device)
|
|
110
|
+
- On iOS, `securityLevel` is normalized by this library (`2` for Secure Enclave-backed keys, `1` for Keychain fallback), not a native Apple numeric level API.
|
|
100
111
|
- `htm` is normalized to uppercase in proof generation.
|
|
101
112
|
- `ath` is derived from `accessToken` (`SHA-256`, base64url) when provided.
|
|
102
113
|
- `jti` and `iat` are auto-generated when omitted.
|
|
@@ -36,6 +36,14 @@ internal class DPoPKeyStore(private val context: Context) {
|
|
|
36
36
|
companion object {
|
|
37
37
|
private const val KEYSTORE_PROVIDER = "AndroidKeyStore"
|
|
38
38
|
private const val EC_CURVE = "secp256r1"
|
|
39
|
+
private const val META_PREFS = "react_native_dpop_keystore_meta"
|
|
40
|
+
private const val META_STRONGBOX_FALLBACK_PREFIX = "strongbox_fallback_reason_"
|
|
41
|
+
private const val REASON_UNAVAILABLE = "UNAVAILABLE"
|
|
42
|
+
private const val REASON_PROVIDER_ERROR = "PROVIDER_ERROR"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private val metadataPrefs by lazy {
|
|
46
|
+
context.getSharedPreferences(META_PREFS, Context.MODE_PRIVATE)
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
private val keyStore: KeyStore by lazy {
|
|
@@ -46,6 +54,7 @@ internal class DPoPKeyStore(private val context: Context) {
|
|
|
46
54
|
if (keyStore.containsAlias(alias)) {
|
|
47
55
|
keyStore.deleteEntry(alias)
|
|
48
56
|
}
|
|
57
|
+
clearStrongBoxFallbackReason(alias)
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
fun generateKeyPair(alias: String): Boolean {
|
|
@@ -56,16 +65,20 @@ internal class DPoPKeyStore(private val context: Context) {
|
|
|
56
65
|
if (keyStore.containsAlias(alias)) {
|
|
57
66
|
keyStore.deleteEntry(alias)
|
|
58
67
|
}
|
|
68
|
+
clearStrongBoxFallbackReason(alias)
|
|
59
69
|
|
|
60
70
|
val generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_PROVIDER)
|
|
61
71
|
if (isStrongBoxEnabled()) {
|
|
62
72
|
try {
|
|
63
73
|
generator.initialize(buildSpec(alias, useStrongBox = true))
|
|
64
74
|
generator.generateKeyPair()
|
|
75
|
+
clearStrongBoxFallbackReason(alias)
|
|
65
76
|
return true
|
|
66
77
|
} catch (_: StrongBoxUnavailableException) {
|
|
78
|
+
storeStrongBoxFallbackReason(alias, REASON_UNAVAILABLE)
|
|
67
79
|
// Fallback to hardware-backed keystore when StrongBox is unavailable.
|
|
68
80
|
} catch (_: ProviderException) {
|
|
81
|
+
storeStrongBoxFallbackReason(alias, REASON_PROVIDER_ERROR)
|
|
69
82
|
// Some devices expose StrongBox but fail during generation.
|
|
70
83
|
}
|
|
71
84
|
}
|
|
@@ -89,6 +102,12 @@ internal class DPoPKeyStore(private val context: Context) {
|
|
|
89
102
|
return privateKey != null && publicKey != null
|
|
90
103
|
}
|
|
91
104
|
|
|
105
|
+
fun isStrongBoxAvailable(): Boolean = isStrongBoxEnabled()
|
|
106
|
+
|
|
107
|
+
fun getStrongBoxFallbackReason(alias: String): String? {
|
|
108
|
+
return metadataPrefs.getString(strongBoxFallbackKey(alias), null)
|
|
109
|
+
}
|
|
110
|
+
|
|
92
111
|
fun getKeyInfo(alias: String): KeyStoreKeyInfo {
|
|
93
112
|
val keyPair = getKeyPair(alias)
|
|
94
113
|
val keyFactory = KeyFactory.getInstance(keyPair.privateKey.algorithm, KEYSTORE_PROVIDER)
|
|
@@ -165,4 +184,14 @@ internal class DPoPKeyStore(private val context: Context) {
|
|
|
165
184
|
false
|
|
166
185
|
}
|
|
167
186
|
}
|
|
187
|
+
|
|
188
|
+
private fun storeStrongBoxFallbackReason(alias: String, reason: String) {
|
|
189
|
+
metadataPrefs.edit().putString(strongBoxFallbackKey(alias), reason).apply()
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private fun clearStrongBoxFallbackReason(alias: String) {
|
|
193
|
+
metadataPrefs.edit().remove(strongBoxFallbackKey(alias)).apply()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun strongBoxFallbackKey(alias: String): String = "$META_STRONGBOX_FALLBACK_PREFIX$alias"
|
|
168
197
|
}
|
|
@@ -70,26 +70,52 @@ class DPoPModule(reactContext: ReactApplicationContext) :
|
|
|
70
70
|
try {
|
|
71
71
|
val effectiveAlias = resolveAlias(alias)
|
|
72
72
|
if (!keyStore.hasKeyPair(effectiveAlias)) {
|
|
73
|
+
val fallbackReason = keyStore.getStrongBoxFallbackReason(effectiveAlias)
|
|
74
|
+
val hardwareAndroid = Arguments.createMap().apply {
|
|
75
|
+
putBoolean("strongBoxAvailable", keyStore.isStrongBoxAvailable())
|
|
76
|
+
putBoolean("strongBoxBacked", false)
|
|
77
|
+
if (fallbackReason != null) {
|
|
78
|
+
putString("strongBoxFallbackReason", fallbackReason)
|
|
79
|
+
} else {
|
|
80
|
+
putNull("strongBoxFallbackReason")
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
val hardware = Arguments.createMap().apply {
|
|
84
|
+
putMap("android", hardwareAndroid)
|
|
85
|
+
}
|
|
73
86
|
val result = Arguments.createMap().apply {
|
|
74
87
|
putString("alias", effectiveAlias)
|
|
75
88
|
putBoolean("hasKeyPair", false)
|
|
89
|
+
putMap("hardware", hardware)
|
|
76
90
|
}
|
|
77
91
|
promise.resolve(result)
|
|
78
92
|
return
|
|
79
93
|
}
|
|
80
94
|
|
|
81
95
|
val keyInfo = keyStore.getKeyInfo(effectiveAlias)
|
|
96
|
+
val fallbackReason = keyStore.getStrongBoxFallbackReason(effectiveAlias)
|
|
97
|
+
val hardwareAndroid = Arguments.createMap().apply {
|
|
98
|
+
putBoolean("strongBoxAvailable", keyInfo.strongBoxAvailable)
|
|
99
|
+
putBoolean("strongBoxBacked", keyInfo.strongBoxBacked)
|
|
100
|
+
if (keyInfo.securityLevel != null) {
|
|
101
|
+
putInt("securityLevel", keyInfo.securityLevel)
|
|
102
|
+
}
|
|
103
|
+
if (fallbackReason != null) {
|
|
104
|
+
putString("strongBoxFallbackReason", fallbackReason)
|
|
105
|
+
} else {
|
|
106
|
+
putNull("strongBoxFallbackReason")
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
val hardware = Arguments.createMap().apply {
|
|
110
|
+
putMap("android", hardwareAndroid)
|
|
111
|
+
}
|
|
82
112
|
val result = Arguments.createMap().apply {
|
|
83
113
|
putString("alias", keyInfo.alias)
|
|
84
114
|
putString("algorithm", keyInfo.algorithm)
|
|
85
115
|
putString("curve", keyInfo.curve)
|
|
86
116
|
putBoolean("hasKeyPair", true)
|
|
87
117
|
putBoolean("insideSecureHardware", keyInfo.insideSecureHardware)
|
|
88
|
-
|
|
89
|
-
putBoolean("strongBoxBacked", keyInfo.strongBoxBacked)
|
|
90
|
-
if (keyInfo.securityLevel != null) {
|
|
91
|
-
putInt("securityLevel", keyInfo.securityLevel)
|
|
92
|
-
}
|
|
118
|
+
putMap("hardware", hardware)
|
|
93
119
|
}
|
|
94
120
|
promise.resolve(result)
|
|
95
121
|
} catch (e: Exception) {
|
package/ios/DPoPKeyStore.swift
CHANGED
|
@@ -12,20 +12,23 @@ struct DPoPKeyInfo {
|
|
|
12
12
|
let curve: String
|
|
13
13
|
let hasKeyPair: Bool
|
|
14
14
|
let insideSecureHardware: Bool
|
|
15
|
-
let strongBoxAvailable: Bool
|
|
16
|
-
let strongBoxBacked: Bool
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
final class DPoPKeyStore {
|
|
20
18
|
private let secureEnclave = SecureEnclaveKeyStore()
|
|
21
19
|
private let keychain = KeychainKeyStore()
|
|
20
|
+
private let fallbackReasonDefaults = UserDefaults.standard
|
|
21
|
+
private let fallbackReasonPrefix = "react_native_dpop_secure_enclave_fallback_reason_"
|
|
22
|
+
private lazy var secureEnclaveAvailable = secureEnclave.isAvailable()
|
|
22
23
|
|
|
23
24
|
func generateKeyPair(alias: String) throws {
|
|
24
25
|
try deleteKeyPair(alias: alias)
|
|
25
26
|
|
|
26
27
|
do {
|
|
27
28
|
try secureEnclave.generateKeyPair(alias: alias)
|
|
29
|
+
clearSecureEnclaveFallbackReason(alias: alias)
|
|
28
30
|
} catch {
|
|
31
|
+
storeSecureEnclaveFallbackReason(alias: alias, reason: mapSecureEnclaveFallbackReason(error))
|
|
29
32
|
try keychain.generateKeyPair(alias: alias)
|
|
30
33
|
}
|
|
31
34
|
}
|
|
@@ -33,6 +36,7 @@ final class DPoPKeyStore {
|
|
|
33
36
|
func deleteKeyPair(alias: String) throws {
|
|
34
37
|
try secureEnclave.deleteKeyPair(alias: alias)
|
|
35
38
|
try keychain.deleteKeyPair(alias: alias)
|
|
39
|
+
clearSecureEnclaveFallbackReason(alias: alias)
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
func hasKeyPair(alias: String) -> Bool {
|
|
@@ -64,9 +68,7 @@ final class DPoPKeyStore {
|
|
|
64
68
|
algorithm: "EC",
|
|
65
69
|
curve: "P-256",
|
|
66
70
|
hasKeyPair: true,
|
|
67
|
-
insideSecureHardware: true
|
|
68
|
-
strongBoxAvailable: false,
|
|
69
|
-
strongBoxBacked: false
|
|
71
|
+
insideSecureHardware: true
|
|
70
72
|
)
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -76,9 +78,7 @@ final class DPoPKeyStore {
|
|
|
76
78
|
algorithm: "EC",
|
|
77
79
|
curve: "P-256",
|
|
78
80
|
hasKeyPair: true,
|
|
79
|
-
insideSecureHardware: false
|
|
80
|
-
strongBoxAvailable: false,
|
|
81
|
-
strongBoxBacked: false
|
|
81
|
+
insideSecureHardware: false
|
|
82
82
|
)
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -87,13 +87,48 @@ final class DPoPKeyStore {
|
|
|
87
87
|
algorithm: "EC",
|
|
88
88
|
curve: "P-256",
|
|
89
89
|
hasKeyPair: false,
|
|
90
|
-
insideSecureHardware: false
|
|
91
|
-
strongBoxAvailable: false,
|
|
92
|
-
strongBoxBacked: false
|
|
90
|
+
insideSecureHardware: false
|
|
93
91
|
)
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
func isHardwareBacked(alias: String) -> Bool {
|
|
97
95
|
secureEnclave.isHardwareBacked(alias: alias)
|
|
98
96
|
}
|
|
97
|
+
|
|
98
|
+
func isSecureEnclaveAvailable() -> Bool {
|
|
99
|
+
secureEnclaveAvailable
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func getSecureEnclaveFallbackReason(alias: String) -> String? {
|
|
103
|
+
fallbackReasonDefaults.string(forKey: fallbackReasonKey(alias: alias))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private func storeSecureEnclaveFallbackReason(alias: String, reason: String) {
|
|
107
|
+
fallbackReasonDefaults.set(reason, forKey: fallbackReasonKey(alias: alias))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private func clearSecureEnclaveFallbackReason(alias: String) {
|
|
111
|
+
fallbackReasonDefaults.removeObject(forKey: fallbackReasonKey(alias: alias))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private func fallbackReasonKey(alias: String) -> String {
|
|
115
|
+
"\(fallbackReasonPrefix)\(alias)"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private func mapSecureEnclaveFallbackReason(_ error: Error) -> String {
|
|
119
|
+
let nsError = error as NSError
|
|
120
|
+
|
|
121
|
+
if nsError.domain == NSOSStatusErrorDomain {
|
|
122
|
+
switch nsError.code {
|
|
123
|
+
case Int(errSecNotAvailable), Int(errSecUnimplemented):
|
|
124
|
+
return "UNAVAILABLE"
|
|
125
|
+
case Int(errSecAuthFailed), Int(errSecInteractionNotAllowed), Int(errSecUserCanceled):
|
|
126
|
+
return "POLICY_REJECTED"
|
|
127
|
+
default:
|
|
128
|
+
return "PROVIDER_ERROR"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return "UNKNOWN"
|
|
133
|
+
}
|
|
99
134
|
}
|
package/ios/DPoPModule.swift
CHANGED
|
@@ -44,23 +44,43 @@ final class DPoPModule {
|
|
|
44
44
|
|
|
45
45
|
func getKeyInfo(alias: String?) -> [String: Any] {
|
|
46
46
|
let effectiveAlias = resolveAlias(alias)
|
|
47
|
+
let secureEnclaveAvailable = keyStore.isSecureEnclaveAvailable()
|
|
48
|
+
let fallbackReason = keyStore.getSecureEnclaveFallbackReason(alias: effectiveAlias)
|
|
49
|
+
let secureEnclaveFallbackReason: Any = fallbackReason ?? NSNull()
|
|
47
50
|
let keyInfo = keyStore.getKeyInfo(alias: effectiveAlias)
|
|
48
51
|
|
|
49
52
|
if !keyInfo.hasKeyPair {
|
|
50
53
|
return [
|
|
51
54
|
"alias": effectiveAlias,
|
|
52
|
-
"hasKeyPair": false
|
|
55
|
+
"hasKeyPair": false,
|
|
56
|
+
"hardware": [
|
|
57
|
+
"ios": [
|
|
58
|
+
"secureEnclaveAvailable": secureEnclaveAvailable,
|
|
59
|
+
"secureEnclaveBacked": false,
|
|
60
|
+
"securityLevel": NSNull(),
|
|
61
|
+
"secureEnclaveFallbackReason": secureEnclaveFallbackReason
|
|
62
|
+
]
|
|
63
|
+
]
|
|
53
64
|
]
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
let secureEnclaveBacked = secureEnclaveAvailable && keyInfo.insideSecureHardware
|
|
68
|
+
let securityLevel = secureEnclaveBacked ? 2 : 1
|
|
69
|
+
|
|
56
70
|
return [
|
|
57
71
|
"alias": keyInfo.alias,
|
|
58
72
|
"algorithm": keyInfo.algorithm,
|
|
59
73
|
"curve": keyInfo.curve,
|
|
60
74
|
"hasKeyPair": true,
|
|
61
|
-
"insideSecureHardware":
|
|
62
|
-
"
|
|
63
|
-
|
|
75
|
+
"insideSecureHardware": secureEnclaveBacked,
|
|
76
|
+
"hardware": [
|
|
77
|
+
"ios": [
|
|
78
|
+
"secureEnclaveAvailable": secureEnclaveAvailable,
|
|
79
|
+
"secureEnclaveBacked": secureEnclaveBacked,
|
|
80
|
+
"securityLevel": securityLevel,
|
|
81
|
+
"secureEnclaveFallbackReason": secureEnclaveFallbackReason
|
|
82
|
+
]
|
|
83
|
+
]
|
|
64
84
|
]
|
|
65
85
|
}
|
|
66
86
|
|
|
@@ -4,6 +4,21 @@ import Security
|
|
|
4
4
|
final class SecureEnclaveKeyStore {
|
|
5
5
|
private let service = "com.dpop.secureenclave"
|
|
6
6
|
|
|
7
|
+
func isAvailable() -> Bool {
|
|
8
|
+
#if targetEnvironment(simulator)
|
|
9
|
+
return false
|
|
10
|
+
#else
|
|
11
|
+
let probeAlias = "__secure_enclave_probe_\(UUID().uuidString)"
|
|
12
|
+
do {
|
|
13
|
+
try generateKeyPair(alias: probeAlias)
|
|
14
|
+
try deleteKeyPair(alias: probeAlias)
|
|
15
|
+
return true
|
|
16
|
+
} catch {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
#endif
|
|
20
|
+
}
|
|
21
|
+
|
|
7
22
|
func generateKeyPair(alias: String) throws {
|
|
8
23
|
try deleteKeyPair(alias: alias)
|
|
9
24
|
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeReactNativeDPoP","DPoP","constructor","proof","proofContext","alias","calculateThumbprint","getPublicKey","format","getPublicKeyDer","getPublicKeyRaw","getPublicKeyJwk","signWithDpopPrivateKey","payload","isBoundToAlias","generateProof","input","result","htu","htm","nonce","accessToken","additional","kid","jti","iat","assertHardwareBacked","deleteKeyPair","getKeyInfo","hasKeyPair","rotateKeyPair"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,qBAAqB,MAAM,4BAAyB;
|
|
1
|
+
{"version":3,"names":["NativeReactNativeDPoP","DPoP","constructor","proof","proofContext","alias","calculateThumbprint","getPublicKey","format","getPublicKeyDer","getPublicKeyRaw","getPublicKeyJwk","signWithDpopPrivateKey","payload","isBoundToAlias","generateProof","input","result","htu","htm","nonce","accessToken","additional","kid","jti","iat","assertHardwareBacked","deleteKeyPair","getKeyInfo","hasKeyPair","rotateKeyPair"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,qBAAqB,MAAM,4BAAyB;AAiE3D,OAAO,MAAMC,IAAI,CAAC;EAKRC,WAAWA,CAACC,KAAa,EAAEC,YAA8B,EAAEC,KAAc,EAAE;IACjF,IAAI,CAACF,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACC,YAAY,GAAGA,YAAY;IAChC,IAAI,CAACC,KAAK,GAAGA,KAAK;EACpB;EAEA,MAAaC,mBAAmBA,CAAA,EAAoB;IAClD,OAAON,qBAAqB,CAACM,mBAAmB,CAAC,IAAI,CAACD,KAAK,IAAI,IAAI,CAAC;EACtE;EAEA,MAAaE,YAAYA,CAACC,MAAuB,EAA+B;IAC9E,IAAIA,MAAM,KAAK,KAAK,EAAE;MACpB,OAAOR,qBAAqB,CAACS,eAAe,CAAC,IAAI,CAACJ,KAAK,IAAI,IAAI,CAAC;IAClE;IACA,IAAIG,MAAM,KAAK,KAAK,EAAE;MACpB,OAAOR,qBAAqB,CAACU,eAAe,CAAC,IAAI,CAACL,KAAK,IAAI,IAAI,CAAC;IAClE;IAEA,OAAOL,qBAAqB,CAACW,eAAe,CAAC,IAAI,CAACN,KAAK,IAAI,IAAI,CAAC;EAClE;EAEA,MAAaO,sBAAsBA,CAACC,OAAe,EAAmB;IACpE,OAAOb,qBAAqB,CAACY,sBAAsB,CAACC,OAAO,EAAE,IAAI,CAACR,KAAK,IAAI,IAAI,CAAC;EAClF;EAEA,MAAaS,cAAcA,CAACT,KAAc,EAAoB;IAC5D,OAAOL,qBAAqB,CAACc,cAAc,CAAC,IAAI,CAACX,KAAK,EAAEE,KAAK,IAAI,IAAI,CAACA,KAAK,IAAI,IAAI,CAAC;EACtF;EAEA,aAAoBU,aAAaA,CAACC,KAAyB,EAAiB;IAC1E,MAAMC,MAAM,GAAI,MAAMjB,qBAAqB,CAACe,aAAa,CACvDC,KAAK,CAACE,GAAG,EACTF,KAAK,CAACG,GAAG,EACTH,KAAK,CAACI,KAAK,IAAI,IAAI,EACnBJ,KAAK,CAACK,WAAW,IAAI,IAAI,EACzBL,KAAK,CAACM,UAAU,IAAI,IAAI,EACxBN,KAAK,CAACO,GAAG,IAAI,IAAI,EACjBP,KAAK,CAACQ,GAAG,IAAI,IAAI,EACjBR,KAAK,CAACS,GAAG,IAAI,IAAI,EACjBT,KAAK,CAACX,KAAK,IAAI,IACjB,CAAyB;IAEzB,OAAO,IAAIJ,IAAI,CAACgB,MAAM,CAACd,KAAK,EAAEc,MAAM,CAACb,YAAY,EAAEY,KAAK,CAACX,KAAK,CAAC;EACjE;EAEA,aAAoBqB,oBAAoBA,CAACrB,KAAc,EAAiB;IACtE,MAAML,qBAAqB,CAAC0B,oBAAoB,CAACrB,KAAK,IAAI,IAAI,CAAC;EACjE;EAEA,aAAoBsB,aAAaA,CAACtB,KAAc,EAAiB;IAC/D,MAAML,qBAAqB,CAAC2B,aAAa,CAACtB,KAAK,IAAI,IAAI,CAAC;EAC1D;EAEA,aAAoBuB,UAAUA,CAACvB,KAAc,EAAwB;IACnE,OAAOL,qBAAqB,CAAC4B,UAAU,CAACvB,KAAK,IAAI,IAAI,CAAC;EACxD;EAEA,aAAoBwB,UAAUA,CAACxB,KAAc,EAAoB;IAC/D,OAAOL,qBAAqB,CAAC6B,UAAU,CAACxB,KAAK,IAAI,IAAI,CAAC;EACxD;EAEA,aAAoByB,aAAaA,CAACzB,KAAc,EAAiB;IAC/D,MAAML,qBAAqB,CAAC8B,aAAa,CAACzB,KAAK,IAAI,IAAI,CAAC;EAC1D;AACF","ignoreList":[]}
|
|
@@ -6,15 +6,27 @@ export type PublicJwk = {
|
|
|
6
6
|
y: string;
|
|
7
7
|
};
|
|
8
8
|
export type PublicKeyFormat = 'JWK' | 'DER' | 'RAW';
|
|
9
|
+
export type SecureHardwareFallbackReason = 'UNAVAILABLE' | 'PROVIDER_ERROR' | 'POLICY_REJECTED' | 'UNKNOWN';
|
|
9
10
|
export type DPoPKeyInfo = {
|
|
10
11
|
alias: string;
|
|
11
12
|
hasKeyPair: boolean;
|
|
12
13
|
algorithm?: string;
|
|
13
14
|
curve?: string;
|
|
14
15
|
insideSecureHardware?: boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
hardware?: {
|
|
17
|
+
android?: {
|
|
18
|
+
strongBoxAvailable: boolean;
|
|
19
|
+
strongBoxBacked: boolean;
|
|
20
|
+
securityLevel?: number;
|
|
21
|
+
strongBoxFallbackReason?: SecureHardwareFallbackReason | null;
|
|
22
|
+
};
|
|
23
|
+
ios?: {
|
|
24
|
+
secureEnclaveAvailable: boolean;
|
|
25
|
+
secureEnclaveBacked: boolean;
|
|
26
|
+
securityLevel?: number | null;
|
|
27
|
+
secureEnclaveFallbackReason?: SecureHardwareFallbackReason | null;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
18
30
|
};
|
|
19
31
|
export type GenerateProofInput = {
|
|
20
32
|
htu: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,IAAI,CAAC;IACV,GAAG,EAAE,OAAO,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-dpop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "React Native library for DPoP proof generation and key management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"example": "yarn workspace react-native-dpop-example",
|
|
52
52
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
53
53
|
"prepare": "bob build",
|
|
54
|
-
"release": "release-it
|
|
54
|
+
"release": "release-it",
|
|
55
|
+
"release:version": "release-it --only-version",
|
|
55
56
|
"test": "jest",
|
|
56
57
|
"typecheck": "tsc"
|
|
57
58
|
},
|
package/src/index.tsx
CHANGED
|
@@ -11,15 +11,28 @@ export type PublicJwk = {
|
|
|
11
11
|
|
|
12
12
|
export type PublicKeyFormat = 'JWK' | 'DER' | 'RAW';
|
|
13
13
|
|
|
14
|
+
export type SecureHardwareFallbackReason = 'UNAVAILABLE' | 'PROVIDER_ERROR' | 'POLICY_REJECTED' | 'UNKNOWN';
|
|
15
|
+
|
|
14
16
|
export type DPoPKeyInfo = {
|
|
15
17
|
alias: string;
|
|
16
18
|
hasKeyPair: boolean;
|
|
17
19
|
algorithm?: string;
|
|
18
20
|
curve?: string;
|
|
19
21
|
insideSecureHardware?: boolean;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
hardware?: {
|
|
23
|
+
android?: {
|
|
24
|
+
strongBoxAvailable: boolean;
|
|
25
|
+
strongBoxBacked: boolean;
|
|
26
|
+
securityLevel?: number;
|
|
27
|
+
strongBoxFallbackReason?: SecureHardwareFallbackReason | null;
|
|
28
|
+
};
|
|
29
|
+
ios?: {
|
|
30
|
+
secureEnclaveAvailable: boolean;
|
|
31
|
+
secureEnclaveBacked: boolean;
|
|
32
|
+
securityLevel?: number | null;
|
|
33
|
+
secureEnclaveFallbackReason?: SecureHardwareFallbackReason | null;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
23
36
|
};
|
|
24
37
|
|
|
25
38
|
export type GenerateProofInput = {
|