@doko/react-native-yubikit 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +126 -0
- package/RNYubikit.podspec +22 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +9 -0
- package/android/src/main/java/com/yubikit/YubiKitManagerHolder.kt +330 -0
- package/android/src/main/java/com/yubikit/YubikitCoreModule.kt +142 -0
- package/android/src/main/java/com/yubikit/YubikitFidoModule.kt +418 -0
- package/android/src/main/java/com/yubikit/YubikitManagementModule.kt +132 -0
- package/android/src/main/java/com/yubikit/YubikitOathModule.kt +224 -0
- package/android/src/main/java/com/yubikit/YubikitOpenPgpModule.kt +317 -0
- package/android/src/main/java/com/yubikit/YubikitPackage.kt +44 -0
- package/android/src/main/java/com/yubikit/YubikitPivModule.kt +310 -0
- package/android/src/main/java/com/yubikit/YubikitSupportModule.kt +108 -0
- package/android/src/main/java/com/yubikit/YubikitYubiOtpModule.kt +248 -0
- package/android/src/main/java/com/yubikit/utils/YubikitUtils.kt +321 -0
- package/ios/YubikitCore.h +5 -0
- package/ios/YubikitCore.mm +101 -0
- package/ios/YubikitDeviceInfoHelper.h +13 -0
- package/ios/YubikitDeviceInfoHelper.mm +110 -0
- package/ios/YubikitFido.h +5 -0
- package/ios/YubikitFido.mm +373 -0
- package/ios/YubikitManagement.h +5 -0
- package/ios/YubikitManagement.mm +153 -0
- package/ios/YubikitManager.h +27 -0
- package/ios/YubikitManager.m +169 -0
- package/ios/YubikitOath.h +5 -0
- package/ios/YubikitOath.mm +583 -0
- package/ios/YubikitOpenPgp.h +5 -0
- package/ios/YubikitOpenPgp.mm +210 -0
- package/ios/YubikitPiv.h +5 -0
- package/ios/YubikitPiv.mm +813 -0
- package/ios/YubikitSupport.h +5 -0
- package/ios/YubikitSupport.mm +58 -0
- package/ios/YubikitYubiOtp.h +5 -0
- package/ios/YubikitYubiOtp.mm +120 -0
- package/lib/module/core.js +34 -0
- package/lib/module/core.js.map +1 -0
- package/lib/module/fido.js +40 -0
- package/lib/module/fido.js.map +1 -0
- package/lib/module/hooks/index.js +5 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/use-yubikey.js +12 -0
- package/lib/module/hooks/use-yubikey.js.map +1 -0
- package/lib/module/hooks/yubikey-provider.js +85 -0
- package/lib/module/hooks/yubikey-provider.js.map +1 -0
- package/lib/module/index.js +12 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/management.js +17 -0
- package/lib/module/management.js.map +1 -0
- package/lib/module/oath.js +53 -0
- package/lib/module/oath.js.map +1 -0
- package/lib/module/openpgp.js +89 -0
- package/lib/module/openpgp.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/piv.js +71 -0
- package/lib/module/piv.js.map +1 -0
- package/lib/module/specs/NativeYubikitCore.js +10 -0
- package/lib/module/specs/NativeYubikitCore.js.map +1 -0
- package/lib/module/specs/NativeYubikitFido.js +5 -0
- package/lib/module/specs/NativeYubikitFido.js.map +1 -0
- package/lib/module/specs/NativeYubikitManagement.js +5 -0
- package/lib/module/specs/NativeYubikitManagement.js.map +1 -0
- package/lib/module/specs/NativeYubikitOath.js +5 -0
- package/lib/module/specs/NativeYubikitOath.js.map +1 -0
- package/lib/module/specs/NativeYubikitOpenPgp.js +5 -0
- package/lib/module/specs/NativeYubikitOpenPgp.js.map +1 -0
- package/lib/module/specs/NativeYubikitPiv.js +5 -0
- package/lib/module/specs/NativeYubikitPiv.js.map +1 -0
- package/lib/module/specs/NativeYubikitSupport.js +5 -0
- package/lib/module/specs/NativeYubikitSupport.js.map +1 -0
- package/lib/module/specs/NativeYubikitYubiOtp.js +5 -0
- package/lib/module/specs/NativeYubikitYubiOtp.js.map +1 -0
- package/lib/module/support.js +11 -0
- package/lib/module/support.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/yubiotp.js +32 -0
- package/lib/module/yubiotp.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/core.d.ts +14 -0
- package/lib/typescript/src/core.d.ts.map +1 -0
- package/lib/typescript/src/fido.d.ts +24 -0
- package/lib/typescript/src/fido.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +3 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/use-yubikey.d.ts +3 -0
- package/lib/typescript/src/hooks/use-yubikey.d.ts.map +1 -0
- package/lib/typescript/src/hooks/yubikey-provider.d.ts +23 -0
- package/lib/typescript/src/hooks/yubikey-provider.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/management.d.ts +8 -0
- package/lib/typescript/src/management.d.ts.map +1 -0
- package/lib/typescript/src/oath.d.ts +20 -0
- package/lib/typescript/src/oath.d.ts.map +1 -0
- package/lib/typescript/src/openpgp.d.ts +35 -0
- package/lib/typescript/src/openpgp.d.ts.map +1 -0
- package/lib/typescript/src/piv.d.ts +26 -0
- package/lib/typescript/src/piv.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitCore.d.ts +49 -0
- package/lib/typescript/src/specs/NativeYubikitCore.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitFido.d.ts +121 -0
- package/lib/typescript/src/specs/NativeYubikitFido.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitManagement.d.ts +53 -0
- package/lib/typescript/src/specs/NativeYubikitManagement.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitOath.d.ts +70 -0
- package/lib/typescript/src/specs/NativeYubikitOath.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts +53 -0
- package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitPiv.d.ts +47 -0
- package/lib/typescript/src/specs/NativeYubikitPiv.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitSupport.d.ts +49 -0
- package/lib/typescript/src/specs/NativeYubikitSupport.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts +45 -0
- package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts.map +1 -0
- package/lib/typescript/src/support.d.ts +6 -0
- package/lib/typescript/src/support.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +293 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/yubiotp.d.ts +13 -0
- package/lib/typescript/src/yubiotp.d.ts.map +1 -0
- package/package.json +181 -0
- package/src/core.ts +58 -0
- package/src/fido.ts +112 -0
- package/src/hooks/index.tsx +2 -0
- package/src/hooks/use-yubikey.tsx +10 -0
- package/src/hooks/yubikey-provider.tsx +146 -0
- package/src/index.tsx +10 -0
- package/src/management.ts +44 -0
- package/src/oath.ts +134 -0
- package/src/openpgp.ts +220 -0
- package/src/piv.ts +193 -0
- package/src/specs/NativeYubikitCore.ts +68 -0
- package/src/specs/NativeYubikitFido.ts +149 -0
- package/src/specs/NativeYubikitManagement.ts +78 -0
- package/src/specs/NativeYubikitOath.ts +110 -0
- package/src/specs/NativeYubikitOpenPgp.ts +148 -0
- package/src/specs/NativeYubikitPiv.ts +108 -0
- package/src/specs/NativeYubikitSupport.ts +61 -0
- package/src/specs/NativeYubikitYubiOtp.ts +82 -0
- package/src/support.ts +18 -0
- package/src/types.ts +404 -0
- package/src/yubiotp.ts +96 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
package com.yubikit
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.yubico.yubikit.oath.OathSession
|
|
7
|
+
import com.yubikit.utils.YubikitUtils.base64Decode
|
|
8
|
+
import com.yubikit.utils.YubikitUtils.base64Encode
|
|
9
|
+
import com.yubikit.utils.YubikitUtils.codeToMap
|
|
10
|
+
import com.yubikit.utils.YubikitUtils.credentialDataFromMap
|
|
11
|
+
import com.yubikit.utils.YubikitUtils.credentialToMap
|
|
12
|
+
import kotlinx.coroutines.CoroutineScope
|
|
13
|
+
import kotlinx.coroutines.Dispatchers
|
|
14
|
+
import kotlinx.coroutines.launch
|
|
15
|
+
|
|
16
|
+
@Suppress("unused")
|
|
17
|
+
class YubikitOathModule(reactContext: ReactApplicationContext) :
|
|
18
|
+
NativeYubikitOathSpec(reactContext) {
|
|
19
|
+
|
|
20
|
+
private val moduleScope = CoroutineScope(Dispatchers.IO)
|
|
21
|
+
|
|
22
|
+
override fun getName(): String = NAME
|
|
23
|
+
|
|
24
|
+
private inline fun <R> withOathSession(
|
|
25
|
+
deviceHandle: String,
|
|
26
|
+
promise: Promise,
|
|
27
|
+
crossinline block: (OathSession) -> R
|
|
28
|
+
) {
|
|
29
|
+
moduleScope.launch {
|
|
30
|
+
try {
|
|
31
|
+
val result = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
32
|
+
OathSession(connection).use { session ->
|
|
33
|
+
block(session)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
@Suppress("UNCHECKED_CAST")
|
|
37
|
+
when (result) {
|
|
38
|
+
is Unit -> promise.resolve(null)
|
|
39
|
+
else -> promise.resolve(result)
|
|
40
|
+
}
|
|
41
|
+
} catch (e: Exception) {
|
|
42
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override fun getDeviceId(deviceHandle: String, promise: Promise) {
|
|
48
|
+
withOathSession(deviceHandle, promise) { it.deviceId }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override fun reset(deviceHandle: String, promise: Promise) {
|
|
52
|
+
withOathSession(deviceHandle, promise) { it.reset() }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
override fun isAccessKeySet(deviceHandle: String, promise: Promise) {
|
|
56
|
+
withOathSession(deviceHandle, promise) { it.isAccessKeySet }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override fun isLocked(deviceHandle: String, promise: Promise) {
|
|
60
|
+
withOathSession(deviceHandle, promise) { it.isLocked }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
override fun unlockWithPassword(deviceHandle: String, password: String, promise: Promise) {
|
|
64
|
+
withOathSession(deviceHandle, promise) { it.unlock(password.toCharArray()) }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override fun unlockWithAccessKey(deviceHandle: String, accessKey: String, promise: Promise) {
|
|
68
|
+
withOathSession(deviceHandle, promise) {
|
|
69
|
+
val key = com.yubikit.utils.YubikitUtils.accessKeyFromBytes(base64Decode(accessKey))
|
|
70
|
+
?: throw IllegalArgumentException("accessKey is required")
|
|
71
|
+
it.unlock(key)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override fun setPassword(deviceHandle: String, password: String, promise: Promise) {
|
|
76
|
+
withOathSession(deviceHandle, promise) { it.setPassword(password.toCharArray()) }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun setAccessKey(deviceHandle: String, accessKey: String, promise: Promise) {
|
|
80
|
+
withOathSession(deviceHandle, promise) {
|
|
81
|
+
it.setAccessKey(base64Decode(accessKey) ?: byteArrayOf())
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun deleteAccessKey(deviceHandle: String, promise: Promise) {
|
|
86
|
+
withOathSession(deviceHandle, promise) { it.deleteAccessKey() }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override fun getCredentials(deviceHandle: String, promise: Promise) {
|
|
90
|
+
moduleScope.launch {
|
|
91
|
+
try {
|
|
92
|
+
val credentials = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
93
|
+
OathSession(connection).use { session ->
|
|
94
|
+
session.credentials
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
val array = Arguments.createArray()
|
|
98
|
+
credentials.forEach { array.pushMap(credentialToMap(it)) }
|
|
99
|
+
promise.resolve(Arguments.createMap().apply { putArray("credentials", array) })
|
|
100
|
+
} catch (e: Exception) {
|
|
101
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
override fun calculateCodes(deviceHandle: String, timestamp: Double?, promise: Promise) {
|
|
107
|
+
moduleScope.launch {
|
|
108
|
+
try {
|
|
109
|
+
val entries = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
110
|
+
OathSession(connection).use { session ->
|
|
111
|
+
if (timestamp != null) session.calculateCodes(timestamp.toLong())
|
|
112
|
+
else session.calculateCodes()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
val array = Arguments.createArray()
|
|
116
|
+
entries.forEach { (credential, code) ->
|
|
117
|
+
array.pushMap(Arguments.createMap().apply {
|
|
118
|
+
putMap("credential", credentialToMap(credential))
|
|
119
|
+
code?.let { putMap("code", codeToMap(it)) }
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
promise.resolve(Arguments.createMap().apply { putArray("codes", array) })
|
|
123
|
+
} catch (e: Exception) {
|
|
124
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
override fun calculateResponse(
|
|
130
|
+
deviceHandle: String,
|
|
131
|
+
credentialId: String,
|
|
132
|
+
challenge: String,
|
|
133
|
+
promise: Promise
|
|
134
|
+
) {
|
|
135
|
+
withOathSession(deviceHandle, promise) {
|
|
136
|
+
base64Encode(
|
|
137
|
+
it.calculateResponse(
|
|
138
|
+
base64Decode(credentialId) ?: byteArrayOf(),
|
|
139
|
+
base64Decode(challenge) ?: byteArrayOf()
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
override fun calculateCode(
|
|
146
|
+
deviceHandle: String,
|
|
147
|
+
credentialId: String,
|
|
148
|
+
timestamp: Double?,
|
|
149
|
+
promise: Promise
|
|
150
|
+
) {
|
|
151
|
+
moduleScope.launch {
|
|
152
|
+
try {
|
|
153
|
+
val code = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
154
|
+
OathSession(connection).use { session ->
|
|
155
|
+
val credential = session.credentials.find {
|
|
156
|
+
it.id.contentEquals(base64Decode(credentialId) ?: byteArrayOf())
|
|
157
|
+
} ?: throw IllegalArgumentException("Credential not found")
|
|
158
|
+
if (timestamp != null) {
|
|
159
|
+
session.calculateCode(credential, timestamp.toLong())
|
|
160
|
+
} else {
|
|
161
|
+
session.calculateCode(credential)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
promise.resolve(codeToMap(code))
|
|
166
|
+
} catch (e: Exception) {
|
|
167
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun putCredential(
|
|
173
|
+
deviceHandle: String,
|
|
174
|
+
credentialData: com.facebook.react.bridge.ReadableMap,
|
|
175
|
+
requireTouch: Boolean,
|
|
176
|
+
promise: Promise
|
|
177
|
+
) {
|
|
178
|
+
moduleScope.launch {
|
|
179
|
+
try {
|
|
180
|
+
val credential = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
181
|
+
OathSession(connection).use { session ->
|
|
182
|
+
session.putCredential(credentialDataFromMap(credentialData), requireTouch)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
promise.resolve(credentialToMap(credential))
|
|
186
|
+
} catch (e: Exception) {
|
|
187
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
override fun deleteCredential(deviceHandle: String, credentialId: String, promise: Promise) {
|
|
193
|
+
withOathSession(deviceHandle, promise) {
|
|
194
|
+
it.deleteCredential(base64Decode(credentialId) ?: byteArrayOf())
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override fun renameCredential(
|
|
199
|
+
deviceHandle: String,
|
|
200
|
+
credentialId: String,
|
|
201
|
+
newAccountName: String,
|
|
202
|
+
newIssuer: String?,
|
|
203
|
+
promise: Promise
|
|
204
|
+
) {
|
|
205
|
+
moduleScope.launch {
|
|
206
|
+
try {
|
|
207
|
+
val credential = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
208
|
+
OathSession(connection).use { session ->
|
|
209
|
+
val cred = session.credentials.find { it.id.contentEquals(base64Decode(credentialId) ?: byteArrayOf()) }
|
|
210
|
+
?: throw IllegalArgumentException("Credential not found")
|
|
211
|
+
session.renameCredential(cred, newAccountName, newIssuer)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
promise.resolve(credentialToMap(credential))
|
|
215
|
+
} catch (e: Exception) {
|
|
216
|
+
promise.reject("OATH_ERROR", e.message, e)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
companion object {
|
|
222
|
+
const val NAME = "YubikitOath"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
package com.yubikit
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.yubico.yubikit.openpgp.KeyRef
|
|
8
|
+
import com.yubico.yubikit.openpgp.OpenPgpSession
|
|
9
|
+
import com.yubico.yubikit.openpgp.OpenPgpCurve
|
|
10
|
+
import com.yubico.yubikit.openpgp.Uif
|
|
11
|
+
import com.yubico.yubikit.openpgp.PinPolicy
|
|
12
|
+
import com.yubikit.utils.YubikitUtils.base64Decode
|
|
13
|
+
import com.yubikit.utils.YubikitUtils.base64Encode
|
|
14
|
+
import com.yubikit.utils.YubikitUtils.versionToMap
|
|
15
|
+
import kotlinx.coroutines.CoroutineScope
|
|
16
|
+
import kotlinx.coroutines.Dispatchers
|
|
17
|
+
import kotlinx.coroutines.launch
|
|
18
|
+
|
|
19
|
+
@Suppress("unused")
|
|
20
|
+
class YubikitOpenPgpModule(reactContext: ReactApplicationContext) :
|
|
21
|
+
NativeYubikitOpenPgpSpec(reactContext) {
|
|
22
|
+
|
|
23
|
+
private val moduleScope = CoroutineScope(Dispatchers.IO)
|
|
24
|
+
|
|
25
|
+
override fun getName(): String = NAME
|
|
26
|
+
|
|
27
|
+
private inline fun <R> withOpenPgpSession(
|
|
28
|
+
deviceHandle: String,
|
|
29
|
+
promise: Promise,
|
|
30
|
+
crossinline block: (OpenPgpSession) -> R
|
|
31
|
+
) {
|
|
32
|
+
moduleScope.launch {
|
|
33
|
+
try {
|
|
34
|
+
val result = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
35
|
+
OpenPgpSession(connection).use { session ->
|
|
36
|
+
block(session)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
@Suppress("UNCHECKED_CAST")
|
|
40
|
+
when (result) {
|
|
41
|
+
is Unit -> promise.resolve(null)
|
|
42
|
+
else -> promise.resolve(result)
|
|
43
|
+
}
|
|
44
|
+
} catch (e: Exception) {
|
|
45
|
+
promise.reject("OPENPGP_ERROR", e.message, e)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private fun keyRefFromString(value: String): KeyRef {
|
|
51
|
+
return KeyRef.valueOf(value)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private fun openPgpCurveFromString(value: String): OpenPgpCurve {
|
|
55
|
+
return OpenPgpCurve.valueOf(value)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private fun uifFromString(value: String): Uif {
|
|
59
|
+
return Uif.valueOf(value)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun pinPolicyFromString(value: String): PinPolicy {
|
|
63
|
+
return PinPolicy.valueOf(value)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override fun getVersion(deviceHandle: String, promise: Promise) {
|
|
67
|
+
withOpenPgpSession(deviceHandle, promise) { versionToMap(it.version) }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override fun getApplicationRelatedData(deviceHandle: String, promise: Promise) {
|
|
71
|
+
moduleScope.launch {
|
|
72
|
+
try {
|
|
73
|
+
val data = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
74
|
+
OpenPgpSession(connection).use { session ->
|
|
75
|
+
session.applicationRelatedData
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
promise.resolve(Arguments.createMap().apply {
|
|
79
|
+
putString("aid", base64Encode(data.aid.bytes))
|
|
80
|
+
putString("historical", base64Encode(data.historical))
|
|
81
|
+
})
|
|
82
|
+
} catch (e: Exception) {
|
|
83
|
+
promise.reject("OPENPGP_ERROR", e.message, e)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
override fun verifyUserPin(
|
|
89
|
+
deviceHandle: String,
|
|
90
|
+
pin: String,
|
|
91
|
+
extended: Boolean?,
|
|
92
|
+
promise: Promise
|
|
93
|
+
) {
|
|
94
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
95
|
+
it.verifyUserPin(pin.toCharArray(), extended ?: false)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
override fun verifyAdminPin(deviceHandle: String, pin: String, promise: Promise) {
|
|
100
|
+
withOpenPgpSession(deviceHandle, promise) { it.verifyAdminPin(pin.toCharArray()) }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
override fun unverifyUserPin(deviceHandle: String, promise: Promise) {
|
|
104
|
+
withOpenPgpSession(deviceHandle, promise) { it.unverifyUserPin() }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
override fun unverifyAdminPin(deviceHandle: String, promise: Promise) {
|
|
108
|
+
withOpenPgpSession(deviceHandle, promise) { it.unverifyAdminPin() }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
override fun getSignatureCounter(deviceHandle: String, promise: Promise) {
|
|
112
|
+
withOpenPgpSession(deviceHandle, promise) { it.signatureCounter }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
override fun getChallenge(deviceHandle: String, length: Double, promise: Promise) {
|
|
116
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
117
|
+
base64Encode(it.getChallenge(length.toInt()))
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
override fun reset(deviceHandle: String, promise: Promise) {
|
|
122
|
+
withOpenPgpSession(deviceHandle, promise) { it.reset() }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override fun setPinAttempts(
|
|
126
|
+
deviceHandle: String,
|
|
127
|
+
userAttempts: Double,
|
|
128
|
+
resetAttempts: Double,
|
|
129
|
+
adminAttempts: Double,
|
|
130
|
+
promise: Promise
|
|
131
|
+
) {
|
|
132
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
133
|
+
it.setPinAttempts(userAttempts.toInt(), resetAttempts.toInt(), adminAttempts.toInt())
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
override fun changeUserPin(
|
|
138
|
+
deviceHandle: String,
|
|
139
|
+
pin: String,
|
|
140
|
+
newPin: String,
|
|
141
|
+
promise: Promise
|
|
142
|
+
) {
|
|
143
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
144
|
+
it.changeUserPin(pin.toCharArray(), newPin.toCharArray())
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
override fun changeAdminPin(
|
|
149
|
+
deviceHandle: String,
|
|
150
|
+
pin: String,
|
|
151
|
+
newPin: String,
|
|
152
|
+
promise: Promise
|
|
153
|
+
) {
|
|
154
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
155
|
+
it.changeAdminPin(pin.toCharArray(), newPin.toCharArray())
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
override fun setSignaturePinPolicy(
|
|
160
|
+
deviceHandle: String,
|
|
161
|
+
policy: String,
|
|
162
|
+
promise: Promise
|
|
163
|
+
) {
|
|
164
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
165
|
+
it.setSignaturePinPolicy(pinPolicyFromString(policy))
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
override fun getUif(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
170
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
171
|
+
it.getUif(keyRefFromString(keyRef)).name
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
override fun setUif(
|
|
176
|
+
deviceHandle: String,
|
|
177
|
+
keyRef: String,
|
|
178
|
+
uif: String,
|
|
179
|
+
promise: Promise
|
|
180
|
+
) {
|
|
181
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
182
|
+
it.setUif(keyRefFromString(keyRef), uifFromString(uif))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
override fun getAlgorithmInformation(deviceHandle: String, promise: Promise) {
|
|
187
|
+
moduleScope.launch {
|
|
188
|
+
try {
|
|
189
|
+
val info = YubiKitManagerHolder.withSmartCard(deviceHandle) { connection ->
|
|
190
|
+
OpenPgpSession(connection).use { session ->
|
|
191
|
+
session.algorithmInformation
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
val result = Arguments.createArray()
|
|
195
|
+
info.forEach { (keyRef, attributes) ->
|
|
196
|
+
val attrArray = Arguments.createArray()
|
|
197
|
+
attributes.forEach { attr ->
|
|
198
|
+
attrArray.pushMap(Arguments.createMap().apply {
|
|
199
|
+
putString("keyRef", keyRef.name)
|
|
200
|
+
putString("attributes", attr.toString())
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
result.pushMap(Arguments.createMap().apply {
|
|
204
|
+
putString("keyRef", keyRef.name)
|
|
205
|
+
putArray("attributes", attrArray)
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
promise.resolve(result)
|
|
209
|
+
} catch (e: Exception) {
|
|
210
|
+
promise.reject("OPENPGP_ERROR", e.message, e)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
override fun setAlgorithmAttributes(
|
|
216
|
+
deviceHandle: String,
|
|
217
|
+
keyRef: String,
|
|
218
|
+
attributes: ReadableMap,
|
|
219
|
+
promise: Promise
|
|
220
|
+
) {
|
|
221
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
222
|
+
// OpenPgp AlgorithmAttributes is complex; expose minimal constructor path.
|
|
223
|
+
throw NotImplementedError("setAlgorithmAttributes requires native-side AlgorithmAttributes construction")
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
override fun getCertificate(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
228
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
229
|
+
base64Encode(it.getCertificate(keyRefFromString(keyRef))?.encoded)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
override fun putCertificate(
|
|
234
|
+
deviceHandle: String,
|
|
235
|
+
keyRef: String,
|
|
236
|
+
certificate: String,
|
|
237
|
+
promise: Promise
|
|
238
|
+
) {
|
|
239
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
240
|
+
val cert = java.security.cert.CertificateFactory.getInstance("X.509")
|
|
241
|
+
.generateCertificate(
|
|
242
|
+
java.io.ByteArrayInputStream(base64Decode(certificate) ?: byteArrayOf())
|
|
243
|
+
) as java.security.cert.X509Certificate
|
|
244
|
+
it.putCertificate(keyRefFromString(keyRef), cert)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
override fun deleteCertificate(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
249
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
250
|
+
it.deleteCertificate(keyRefFromString(keyRef))
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
override fun generateRsaKey(
|
|
255
|
+
deviceHandle: String,
|
|
256
|
+
keyRef: String,
|
|
257
|
+
keySize: Double,
|
|
258
|
+
promise: Promise
|
|
259
|
+
) {
|
|
260
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
261
|
+
base64Encode(it.generateRsaKey(keyRefFromString(keyRef), keySize.toInt()).encoded)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
override fun generateEcKey(
|
|
266
|
+
deviceHandle: String,
|
|
267
|
+
keyRef: String,
|
|
268
|
+
curve: String,
|
|
269
|
+
promise: Promise
|
|
270
|
+
) {
|
|
271
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
272
|
+
base64Encode(
|
|
273
|
+
it.generateEcKey(keyRefFromString(keyRef), openPgpCurveFromString(curve)).encoded
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
override fun getPublicKey(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
279
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
280
|
+
base64Encode(it.getPublicKey(keyRefFromString(keyRef)).encoded)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
override fun deleteKey(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
285
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
286
|
+
it.deleteKey(keyRefFromString(keyRef))
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
override fun sign(deviceHandle: String, payload: String, promise: Promise) {
|
|
291
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
292
|
+
base64Encode(it.sign(base64Decode(payload) ?: byteArrayOf()))
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
override fun decrypt(deviceHandle: String, payload: String, promise: Promise) {
|
|
297
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
298
|
+
base64Encode(it.decrypt(base64Decode(payload) ?: byteArrayOf()))
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
override fun authenticate(deviceHandle: String, payload: String, promise: Promise) {
|
|
303
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
304
|
+
base64Encode(it.authenticate(base64Decode(payload) ?: byteArrayOf()))
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
override fun attestKey(deviceHandle: String, keyRef: String, promise: Promise) {
|
|
309
|
+
withOpenPgpSession(deviceHandle, promise) {
|
|
310
|
+
base64Encode(it.attestKey(keyRefFromString(keyRef)).encoded)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
companion object {
|
|
315
|
+
const val NAME = "YubikitOpenPgp"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package com.yubikit
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.NativeModule
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
7
|
+
|
|
8
|
+
class YubikitPackage : com.facebook.react.BaseReactPackage() {
|
|
9
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
10
|
+
return when (name) {
|
|
11
|
+
YubikitCoreModule.NAME -> YubikitCoreModule(reactContext)
|
|
12
|
+
YubikitManagementModule.NAME -> YubikitManagementModule(reactContext)
|
|
13
|
+
YubikitOathModule.NAME -> YubikitOathModule(reactContext)
|
|
14
|
+
YubikitPivModule.NAME -> YubikitPivModule(reactContext)
|
|
15
|
+
YubikitOpenPgpModule.NAME -> YubikitOpenPgpModule(reactContext)
|
|
16
|
+
YubikitYubiOtpModule.NAME -> YubikitYubiOtpModule(reactContext)
|
|
17
|
+
YubikitFidoModule.NAME -> YubikitFidoModule(reactContext)
|
|
18
|
+
YubikitSupportModule.NAME -> YubikitSupportModule(reactContext)
|
|
19
|
+
else -> null
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
|
|
24
|
+
mapOf(
|
|
25
|
+
YubikitCoreModule.NAME to moduleInfo(YubikitCoreModule.NAME),
|
|
26
|
+
YubikitManagementModule.NAME to moduleInfo(YubikitManagementModule.NAME),
|
|
27
|
+
YubikitOathModule.NAME to moduleInfo(YubikitOathModule.NAME),
|
|
28
|
+
YubikitPivModule.NAME to moduleInfo(YubikitPivModule.NAME),
|
|
29
|
+
YubikitOpenPgpModule.NAME to moduleInfo(YubikitOpenPgpModule.NAME),
|
|
30
|
+
YubikitYubiOtpModule.NAME to moduleInfo(YubikitYubiOtpModule.NAME),
|
|
31
|
+
YubikitFidoModule.NAME to moduleInfo(YubikitFidoModule.NAME),
|
|
32
|
+
YubikitSupportModule.NAME to moduleInfo(YubikitSupportModule.NAME)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private fun moduleInfo(name: String) = ReactModuleInfo(
|
|
37
|
+
name = name,
|
|
38
|
+
className = name,
|
|
39
|
+
canOverrideExistingModule = false,
|
|
40
|
+
needsEagerInit = false,
|
|
41
|
+
isCxxModule = false,
|
|
42
|
+
isTurboModule = true
|
|
43
|
+
)
|
|
44
|
+
}
|