@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,321 @@
|
|
|
1
|
+
package com.yubikit.utils
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import android.util.Base64
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.facebook.react.bridge.WritableArray
|
|
9
|
+
import com.facebook.react.bridge.WritableMap
|
|
10
|
+
import com.yubico.yubikit.core.Transport
|
|
11
|
+
import com.yubico.yubikit.core.Version
|
|
12
|
+
import com.yubico.yubikit.core.UsbInterface
|
|
13
|
+
import com.yubico.yubikit.management.Capability
|
|
14
|
+
import com.yubico.yubikit.management.DeviceConfig
|
|
15
|
+
import com.yubico.yubikit.management.DeviceInfo
|
|
16
|
+
import com.yubico.yubikit.management.FormFactor
|
|
17
|
+
import com.yubico.yubikit.oath.AccessKey
|
|
18
|
+
import com.yubico.yubikit.oath.Code
|
|
19
|
+
import com.yubico.yubikit.oath.Credential
|
|
20
|
+
import com.yubico.yubikit.oath.CredentialData
|
|
21
|
+
import com.yubico.yubikit.oath.HashAlgorithm
|
|
22
|
+
import com.yubico.yubikit.oath.OathType
|
|
23
|
+
import com.yubico.yubikit.piv.KeyType
|
|
24
|
+
import com.yubico.yubikit.piv.ManagementKeyType
|
|
25
|
+
import com.yubico.yubikit.piv.PinPolicy
|
|
26
|
+
import com.yubico.yubikit.piv.Slot
|
|
27
|
+
import com.yubico.yubikit.piv.TouchPolicy
|
|
28
|
+
import javax.crypto.Mac
|
|
29
|
+
import javax.crypto.spec.SecretKeySpec
|
|
30
|
+
|
|
31
|
+
object YubikitUtils {
|
|
32
|
+
|
|
33
|
+
@JvmStatic
|
|
34
|
+
fun base64Encode(bytes: ByteArray?): String? {
|
|
35
|
+
return bytes?.let { Base64.encodeToString(it, Base64.NO_WRAP) }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@JvmStatic
|
|
39
|
+
fun base64Decode(encoded: String?): ByteArray? {
|
|
40
|
+
return encoded?.let { Base64.decode(it, Base64.DEFAULT) }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@JvmStatic
|
|
44
|
+
fun versionToMap(version: Version): WritableMap {
|
|
45
|
+
return Arguments.createMap().apply {
|
|
46
|
+
putInt("major", version.major.toInt())
|
|
47
|
+
putInt("minor", version.minor.toInt())
|
|
48
|
+
putInt("micro", version.micro.toInt())
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@JvmStatic
|
|
53
|
+
fun parseVersion(map: ReadableMap?): Version? {
|
|
54
|
+
if (map == null) return null
|
|
55
|
+
return Version(
|
|
56
|
+
map.getInt("major"),
|
|
57
|
+
map.getInt("minor"),
|
|
58
|
+
map.getInt("micro")
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@JvmStatic
|
|
63
|
+
fun transportFromString(value: String?): Transport {
|
|
64
|
+
return when (value?.uppercase()) {
|
|
65
|
+
"USB" -> Transport.USB
|
|
66
|
+
"NFC" -> Transport.NFC
|
|
67
|
+
else -> throw IllegalArgumentException("Unknown transport: $value")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@JvmStatic
|
|
72
|
+
fun transportToString(transport: Transport): String {
|
|
73
|
+
return transport.name
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@JvmStatic
|
|
77
|
+
fun capabilityToString(capability: Capability): String {
|
|
78
|
+
return capability.name
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@JvmStatic
|
|
82
|
+
fun capabilityFromString(value: String): Capability {
|
|
83
|
+
return Capability.valueOf(value)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@JvmStatic
|
|
87
|
+
fun formFactorToString(formFactor: FormFactor): String {
|
|
88
|
+
return formFactor.name
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@JvmStatic
|
|
92
|
+
fun formFactorFromString(value: String): FormFactor {
|
|
93
|
+
return FormFactor.valueOf(value)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@JvmStatic
|
|
97
|
+
fun oathTypeFromString(value: String): OathType {
|
|
98
|
+
return OathType.valueOf(value)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@JvmStatic
|
|
102
|
+
fun oathTypeToString(type: OathType): String {
|
|
103
|
+
return type.name
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@JvmStatic
|
|
107
|
+
fun hashAlgorithmFromString(value: String): HashAlgorithm {
|
|
108
|
+
return HashAlgorithm.valueOf(value)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@JvmStatic
|
|
112
|
+
fun hashAlgorithmToString(algorithm: HashAlgorithm): String {
|
|
113
|
+
return algorithm.name
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@JvmStatic
|
|
117
|
+
fun slotFromString(value: String): Slot {
|
|
118
|
+
return Slot.valueOf(value)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@JvmStatic
|
|
122
|
+
fun slotToString(slot: Slot): String {
|
|
123
|
+
return slot.name
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@JvmStatic
|
|
127
|
+
fun keyTypeFromString(value: String): KeyType {
|
|
128
|
+
return KeyType.valueOf(value)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@JvmStatic
|
|
132
|
+
fun keyTypeToString(keyType: KeyType): String {
|
|
133
|
+
return keyType.name
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@JvmStatic
|
|
137
|
+
fun pinPolicyFromString(value: String): PinPolicy {
|
|
138
|
+
return PinPolicy.valueOf(value)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@JvmStatic
|
|
142
|
+
fun pinPolicyToString(policy: PinPolicy): String {
|
|
143
|
+
return policy.name
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@JvmStatic
|
|
147
|
+
fun touchPolicyFromString(value: String): TouchPolicy {
|
|
148
|
+
return TouchPolicy.valueOf(value)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@JvmStatic
|
|
152
|
+
fun touchPolicyToString(policy: TouchPolicy): String {
|
|
153
|
+
return policy.name
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@JvmStatic
|
|
157
|
+
fun managementKeyTypeFromString(value: String): ManagementKeyType {
|
|
158
|
+
return ManagementKeyType.valueOf(value)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@JvmStatic
|
|
162
|
+
fun managementKeyTypeToString(type: ManagementKeyType): String {
|
|
163
|
+
return type.name
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@JvmStatic
|
|
167
|
+
fun deviceInfoToMap(info: DeviceInfo): WritableMap {
|
|
168
|
+
return Arguments.createMap().apply {
|
|
169
|
+
putMap("version", versionToMap(info.version))
|
|
170
|
+
putString("versionName", info.versionName)
|
|
171
|
+
putString("formFactor", formFactorToString(info.formFactor))
|
|
172
|
+
info.serialNumber?.let { putInt("serialNumber", it) }
|
|
173
|
+
putBoolean("isLocked", info.isLocked)
|
|
174
|
+
putBoolean("isFips", info.isFips)
|
|
175
|
+
putBoolean("isSky", info.isSky)
|
|
176
|
+
info.partNumber?.let { putString("partNumber", it) }
|
|
177
|
+
putInt("fipsCapable", info.fipsCapable)
|
|
178
|
+
putInt("fipsApproved", info.fipsApproved)
|
|
179
|
+
putBoolean("pinComplexity", info.pinComplexity)
|
|
180
|
+
putInt("resetBlocked", info.resetBlocked)
|
|
181
|
+
putMap("supportedCapabilities", capabilitiesToMap(info))
|
|
182
|
+
putBoolean("hasTransportUsb", info.hasTransport(Transport.USB))
|
|
183
|
+
putBoolean("hasTransportNfc", info.hasTransport(Transport.NFC))
|
|
184
|
+
info.config?.let { putMap("config", deviceConfigToMap(it)) }
|
|
185
|
+
info.fpsVersion?.let { putMap("fpsVersion", versionToMap(it)) }
|
|
186
|
+
info.stmVersion?.let { putMap("stmVersion", versionToMap(it)) }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@JvmStatic
|
|
191
|
+
fun capabilitiesToMap(info: DeviceInfo): WritableMap {
|
|
192
|
+
return Arguments.createMap().apply {
|
|
193
|
+
listOf(Transport.USB, Transport.NFC).forEach { transport ->
|
|
194
|
+
info.getSupportedCapabilities(transport)?.let { value ->
|
|
195
|
+
putInt(transport.name.lowercase(), value)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@JvmStatic
|
|
202
|
+
fun deviceConfigToMap(config: DeviceConfig): WritableMap {
|
|
203
|
+
return Arguments.createMap().apply {
|
|
204
|
+
val capsMap = Arguments.createMap()
|
|
205
|
+
var hasCaps = false
|
|
206
|
+
listOf(Transport.USB, Transport.NFC).forEach { transport ->
|
|
207
|
+
config.getEnabledCapabilities(transport)?.let { value ->
|
|
208
|
+
capsMap.putInt(transport.name.lowercase(), value)
|
|
209
|
+
hasCaps = true
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (hasCaps) {
|
|
213
|
+
putMap("enabledCapabilities", capsMap)
|
|
214
|
+
}
|
|
215
|
+
config.autoEjectTimeout?.let { putInt("autoEjectTimeout", it.toInt()) }
|
|
216
|
+
config.challengeResponseTimeout?.let { putInt("challengeResponseTimeout", it.toInt()) }
|
|
217
|
+
config.nfcRestricted?.let { putBoolean("nfcRestricted", it) }
|
|
218
|
+
config.deviceFlags?.let { putInt("deviceFlags", it) }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@JvmStatic
|
|
223
|
+
fun parseDeviceConfig(map: ReadableMap?): DeviceConfig {
|
|
224
|
+
if (map == null) return DeviceConfig.Builder().build()
|
|
225
|
+
val builder = DeviceConfig.Builder()
|
|
226
|
+
map.getMap("enabledCapabilities")?.let { capsMap ->
|
|
227
|
+
listOf(Transport.USB, Transport.NFC).forEach { transport ->
|
|
228
|
+
val key = transport.name.lowercase()
|
|
229
|
+
if (capsMap.hasKey(key) && !capsMap.isNull(key)) {
|
|
230
|
+
builder.enabledCapabilities(transport, capsMap.getInt(key))
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (map.hasKey("autoEjectTimeout") && !map.isNull("autoEjectTimeout")) {
|
|
235
|
+
builder.autoEjectTimeout(map.getInt("autoEjectTimeout").toShort())
|
|
236
|
+
}
|
|
237
|
+
if (map.hasKey("challengeResponseTimeout") && !map.isNull("challengeResponseTimeout")) {
|
|
238
|
+
builder.challengeResponseTimeout(map.getInt("challengeResponseTimeout").toByte())
|
|
239
|
+
}
|
|
240
|
+
if (map.hasKey("nfcRestricted") && !map.isNull("nfcRestricted")) {
|
|
241
|
+
builder.nfcRestricted(map.getBoolean("nfcRestricted"))
|
|
242
|
+
}
|
|
243
|
+
if (map.hasKey("deviceFlags") && !map.isNull("deviceFlags")) {
|
|
244
|
+
builder.deviceFlags(map.getInt("deviceFlags"))
|
|
245
|
+
}
|
|
246
|
+
return builder.build()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@JvmStatic
|
|
250
|
+
fun credentialToMap(credential: Credential): WritableMap {
|
|
251
|
+
return Arguments.createMap().apply {
|
|
252
|
+
putString("id", base64Encode(credential.id))
|
|
253
|
+
putString("oathType", oathTypeToString(credential.oathType))
|
|
254
|
+
putString("accountName", credential.accountName)
|
|
255
|
+
credential.issuer?.let { putString("issuer", it) }
|
|
256
|
+
putInt("period", credential.period)
|
|
257
|
+
putBoolean("touchRequired", credential.isTouchRequired)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@JvmStatic
|
|
262
|
+
fun credentialDataFromMap(map: ReadableMap): CredentialData {
|
|
263
|
+
return CredentialData(
|
|
264
|
+
map.getString("accountName") ?: "",
|
|
265
|
+
oathTypeFromString(map.getString("oathType") ?: "TOTP"),
|
|
266
|
+
hashAlgorithmFromString(map.getString("hashAlgorithm") ?: "SHA1"),
|
|
267
|
+
base64Decode(map.getString("secret")) ?: byteArrayOf(),
|
|
268
|
+
map.getInt("digits"),
|
|
269
|
+
map.getInt("period"),
|
|
270
|
+
map.getInt("counter"),
|
|
271
|
+
map.getString("issuer")
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@JvmStatic
|
|
276
|
+
fun codeToMap(code: Code): WritableMap {
|
|
277
|
+
return Arguments.createMap().apply {
|
|
278
|
+
putString("value", code.value)
|
|
279
|
+
putDouble("validFrom", code.validFrom.toDouble())
|
|
280
|
+
putDouble("validUntil", code.validUntil.toDouble())
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@JvmStatic
|
|
285
|
+
fun parseUsbMode(mode: String): UsbInterface.Mode {
|
|
286
|
+
return UsbInterface.Mode.valueOf(mode)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@JvmStatic
|
|
290
|
+
fun readableArrayToBytes(array: ReadableArray?): ByteArray? {
|
|
291
|
+
if (array == null) return null
|
|
292
|
+
return ByteArray(array.size()) { array.getInt(it).toByte() }
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@JvmStatic
|
|
296
|
+
fun bytesToWritableArray(bytes: ByteArray?): WritableArray? {
|
|
297
|
+
if (bytes == null) return null
|
|
298
|
+
return Arguments.createArray().apply {
|
|
299
|
+
bytes.forEach { pushInt(it.toInt()) }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@JvmStatic
|
|
304
|
+
fun Bundle.toWritableMap(): WritableMap {
|
|
305
|
+
return Arguments.fromBundle(this)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@JvmStatic
|
|
309
|
+
fun accessKeyFromBytes(key: ByteArray?): AccessKey? {
|
|
310
|
+
if (key == null) return null
|
|
311
|
+
return ByteArrayAccessKey(key)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private class ByteArrayAccessKey(private val key: ByteArray) : AccessKey {
|
|
316
|
+
override fun calculateResponse(challenge: ByteArray): ByteArray {
|
|
317
|
+
val mac = Mac.getInstance("HmacSHA1")
|
|
318
|
+
mac.init(SecretKeySpec(key, "HmacSHA1"))
|
|
319
|
+
return mac.doFinal(challenge)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#import "YubikitCore.h"
|
|
2
|
+
#import "YubikitManager.h"
|
|
3
|
+
#import <YubiKit/YubiKit.h>
|
|
4
|
+
|
|
5
|
+
@implementation YubikitCore
|
|
6
|
+
|
|
7
|
+
RCT_EXPORT_MODULE(YubikitCore)
|
|
8
|
+
|
|
9
|
+
- (instancetype)init {
|
|
10
|
+
self = [super init];
|
|
11
|
+
if (self) {
|
|
12
|
+
__weak YubikitCore *weakSelf = self;
|
|
13
|
+
[YubikitManager shared].eventHandler = ^(NSString *type, NSDictionary * _Nullable payload) {
|
|
14
|
+
YubikitCore *strongSelf = weakSelf;
|
|
15
|
+
if (strongSelf == nil) return;
|
|
16
|
+
NSMutableDictionary *body = [NSMutableDictionary dictionaryWithDictionary:payload ?: @{}];
|
|
17
|
+
body[@"type"] = type;
|
|
18
|
+
[strongSelf emitOnYubiKeyEvent:body];
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return self;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (void)startUsbDiscovery:(JS::NativeYubikitCore::UsbConfiguration &)config {
|
|
25
|
+
[[YubikitManager shared] startUsbDiscovery];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
- (void)stopUsbDiscovery {
|
|
29
|
+
[[YubikitManager shared] stopUsbDiscovery];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
- (void)startNfcDiscovery:(JS::NativeYubikitCore::NfcConfiguration &)config {
|
|
33
|
+
[[YubikitManager shared] startNfcDiscovery];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)stopNfcDiscovery {
|
|
37
|
+
[[YubikitManager shared] stopNfcDiscovery];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
- (void)requestConnection:(NSString *)deviceHandle
|
|
41
|
+
connectionType:(NSString *)connectionType
|
|
42
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
43
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
44
|
+
id<YKFConnectionProtocol> connection = [[YubikitManager shared] connectionForHandle:deviceHandle];
|
|
45
|
+
if (connection == nil) {
|
|
46
|
+
reject(@"CONNECTION_ERROR", @"No device found for handle", nil);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
resolve(deviceHandle);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
- (void)sendApdu:(NSString *)connectionHandle
|
|
53
|
+
apdu:(NSString *)apdu
|
|
54
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
55
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
56
|
+
id<YKFConnectionProtocol> connection = [[YubikitManager shared] connectionForHandle:connectionHandle];
|
|
57
|
+
if (connection == nil) {
|
|
58
|
+
reject(@"CONNECTION_ERROR", @"No device found for handle", nil);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
NSData *apduData = [[NSData alloc] initWithBase64EncodedString:apdu options:0];
|
|
63
|
+
if (apduData == nil) {
|
|
64
|
+
reject(@"APDU_ERROR", @"Invalid base64 APDU", nil);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
YKFAPDU *command = [[YKFAPDU alloc] initWithData:apduData];
|
|
69
|
+
if (command == nil) {
|
|
70
|
+
reject(@"APDU_ERROR", @"Invalid APDU", nil);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
YKFSmartCardInterface *interface = connection.smartCardInterface;
|
|
75
|
+
if (interface == nil) {
|
|
76
|
+
reject(@"APDU_ERROR", @"Smart card interface not available", nil);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
[interface executeCommand:command completion:^(NSData * _Nullable response, NSError * _Nullable error) {
|
|
81
|
+
if (error) {
|
|
82
|
+
reject(@"APDU_ERROR", error.localizedDescription, error);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
resolve([response base64EncodedStringWithOptions:0]);
|
|
86
|
+
}];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
- (void)closeConnection:(NSString *)connectionHandle {
|
|
90
|
+
[[YubikitManager shared] removeConnectionForHandle:connectionHandle];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
- (NSArray<NSDictionary *> *)getDiscoveredDevices {
|
|
94
|
+
return [[YubikitManager shared] listDevices];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
98
|
+
return std::make_shared<facebook::react::NativeYubikitCoreSpecJSI>(params);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
@class YKFManagementDeviceInfo;
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface YubikitDeviceInfoHelper : NSObject
|
|
8
|
+
|
|
9
|
+
+ (NSDictionary *)dictionaryFromDeviceInfo:(YKFManagementDeviceInfo *)deviceInfo;
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#import "YubikitDeviceInfoHelper.h"
|
|
2
|
+
#import <YubiKit/YubiKit.h>
|
|
3
|
+
|
|
4
|
+
@implementation YubikitDeviceInfoHelper
|
|
5
|
+
|
|
6
|
+
+ (NSDictionary *)dictionaryFromDeviceInfo:(YKFManagementDeviceInfo *)deviceInfo {
|
|
7
|
+
YKFManagementInterfaceConfiguration *config = deviceInfo.configuration;
|
|
8
|
+
NSMutableDictionary *result = [NSMutableDictionary dictionary];
|
|
9
|
+
|
|
10
|
+
YKFVersion *version = deviceInfo.version;
|
|
11
|
+
NSString *versionName = [NSString stringWithFormat:@"%d.%d.%d", version.major, version.minor, version.micro];
|
|
12
|
+
result[@"version"] = @{
|
|
13
|
+
@"major": @(version.major),
|
|
14
|
+
@"minor": @(version.minor),
|
|
15
|
+
@"micro": @(version.micro)
|
|
16
|
+
};
|
|
17
|
+
result[@"versionName"] = versionName;
|
|
18
|
+
|
|
19
|
+
NSString *formFactor = @"UNKNOWN";
|
|
20
|
+
switch (deviceInfo.formFactor) {
|
|
21
|
+
case YKFFormFactorUSBAKeychain:
|
|
22
|
+
formFactor = @"USB_A_KEYCHAIN";
|
|
23
|
+
break;
|
|
24
|
+
case YKFFormFactorUSBANano:
|
|
25
|
+
formFactor = @"USB_A_NANO";
|
|
26
|
+
break;
|
|
27
|
+
case YKFFormFactorUSBCKeychain:
|
|
28
|
+
formFactor = @"USB_C_KEYCHAIN";
|
|
29
|
+
break;
|
|
30
|
+
case YKFFormFactorUSBCNano:
|
|
31
|
+
formFactor = @"USB_C_NANO";
|
|
32
|
+
break;
|
|
33
|
+
case YKFFormFactorUSBCLightning:
|
|
34
|
+
formFactor = @"USB_C_LIGHTNING";
|
|
35
|
+
break;
|
|
36
|
+
case YKFFormFactorUSBABio:
|
|
37
|
+
formFactor = @"USB_A_BIO";
|
|
38
|
+
break;
|
|
39
|
+
case YKFFormFactorUSBCBio:
|
|
40
|
+
formFactor = @"USB_C_BIO";
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
result[@"formFactor"] = formFactor;
|
|
46
|
+
|
|
47
|
+
result[@"serialNumber"] = @(deviceInfo.serialNumber);
|
|
48
|
+
result[@"isLocked"] = @(deviceInfo.isConfigurationLocked);
|
|
49
|
+
if (deviceInfo.partNumber != nil) {
|
|
50
|
+
result[@"partNumber"] = deviceInfo.partNumber;
|
|
51
|
+
}
|
|
52
|
+
if (deviceInfo.fpsVersion != nil) {
|
|
53
|
+
result[@"fpsVersion"] = @{
|
|
54
|
+
@"major": @(deviceInfo.fpsVersion.major),
|
|
55
|
+
@"minor": @(deviceInfo.fpsVersion.minor),
|
|
56
|
+
@"micro": @(deviceInfo.fpsVersion.micro)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (deviceInfo.stmVersion != nil) {
|
|
60
|
+
result[@"stmVersion"] = @{
|
|
61
|
+
@"major": @(deviceInfo.stmVersion.major),
|
|
62
|
+
@"minor": @(deviceInfo.stmVersion.minor),
|
|
63
|
+
@"micro": @(deviceInfo.stmVersion.micro)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (config) {
|
|
68
|
+
// Read the raw bitmasks directly rather than re-deriving them by iterating a
|
|
69
|
+
// hardcoded list of YKFManagementApplicationType values - that list previously
|
|
70
|
+
// omitted YKFManagementApplicationTypeHSMAUTH, silently zeroing that bit for
|
|
71
|
+
// every device regardless of actual capability.
|
|
72
|
+
NSUInteger usbSupported = config.usbSupportedMask;
|
|
73
|
+
NSUInteger nfcSupported = config.nfcSupportedMask;
|
|
74
|
+
NSUInteger usbEnabled = config.usbEnabledMask;
|
|
75
|
+
NSUInteger nfcEnabled = config.nfcEnabledMask;
|
|
76
|
+
|
|
77
|
+
result[@"config"] = @{
|
|
78
|
+
@"enabledCapabilities": @{
|
|
79
|
+
@"usb": @(usbEnabled),
|
|
80
|
+
@"nfc": @(nfcEnabled)
|
|
81
|
+
},
|
|
82
|
+
@"autoEjectTimeout": @(config.autoEjectTimeout),
|
|
83
|
+
@"challengeResponseTimeout": @(config.challengeResponseTimeout),
|
|
84
|
+
@"nfcRestricted": @(config.isNFCRestricted)
|
|
85
|
+
// deviceFlags has no public accessor on YKFManagementInterfaceConfiguration in
|
|
86
|
+
// this SDK version, so it can't be populated here (matches Android parity gap).
|
|
87
|
+
};
|
|
88
|
+
result[@"supportedCapabilities"] = @{
|
|
89
|
+
@"usb": @(usbSupported),
|
|
90
|
+
@"nfc": @(nfcSupported)
|
|
91
|
+
};
|
|
92
|
+
result[@"hasTransportUsb"] = @(usbSupported != 0);
|
|
93
|
+
result[@"hasTransportNfc"] = @(nfcSupported != 0);
|
|
94
|
+
} else {
|
|
95
|
+
result[@"supportedCapabilities"] = @{};
|
|
96
|
+
result[@"hasTransportUsb"] = @NO;
|
|
97
|
+
result[@"hasTransportNfc"] = @NO;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
result[@"isFips"] = @(deviceInfo.isFips);
|
|
101
|
+
result[@"isSky"] = @(deviceInfo.isSky);
|
|
102
|
+
result[@"fipsCapable"] = @(deviceInfo.isFIPSCapable);
|
|
103
|
+
result[@"fipsApproved"] = @(deviceInfo.isFIPSApproved);
|
|
104
|
+
result[@"pinComplexity"] = @(deviceInfo.pinComplexity);
|
|
105
|
+
result[@"resetBlocked"] = @(deviceInfo.isResetBlocked);
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@end
|