@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.
Files changed (144) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +126 -0
  3. package/RNYubikit.podspec +22 -0
  4. package/android/build.gradle +63 -0
  5. package/android/src/main/AndroidManifest.xml +9 -0
  6. package/android/src/main/java/com/yubikit/YubiKitManagerHolder.kt +330 -0
  7. package/android/src/main/java/com/yubikit/YubikitCoreModule.kt +142 -0
  8. package/android/src/main/java/com/yubikit/YubikitFidoModule.kt +418 -0
  9. package/android/src/main/java/com/yubikit/YubikitManagementModule.kt +132 -0
  10. package/android/src/main/java/com/yubikit/YubikitOathModule.kt +224 -0
  11. package/android/src/main/java/com/yubikit/YubikitOpenPgpModule.kt +317 -0
  12. package/android/src/main/java/com/yubikit/YubikitPackage.kt +44 -0
  13. package/android/src/main/java/com/yubikit/YubikitPivModule.kt +310 -0
  14. package/android/src/main/java/com/yubikit/YubikitSupportModule.kt +108 -0
  15. package/android/src/main/java/com/yubikit/YubikitYubiOtpModule.kt +248 -0
  16. package/android/src/main/java/com/yubikit/utils/YubikitUtils.kt +321 -0
  17. package/ios/YubikitCore.h +5 -0
  18. package/ios/YubikitCore.mm +101 -0
  19. package/ios/YubikitDeviceInfoHelper.h +13 -0
  20. package/ios/YubikitDeviceInfoHelper.mm +110 -0
  21. package/ios/YubikitFido.h +5 -0
  22. package/ios/YubikitFido.mm +373 -0
  23. package/ios/YubikitManagement.h +5 -0
  24. package/ios/YubikitManagement.mm +153 -0
  25. package/ios/YubikitManager.h +27 -0
  26. package/ios/YubikitManager.m +169 -0
  27. package/ios/YubikitOath.h +5 -0
  28. package/ios/YubikitOath.mm +583 -0
  29. package/ios/YubikitOpenPgp.h +5 -0
  30. package/ios/YubikitOpenPgp.mm +210 -0
  31. package/ios/YubikitPiv.h +5 -0
  32. package/ios/YubikitPiv.mm +813 -0
  33. package/ios/YubikitSupport.h +5 -0
  34. package/ios/YubikitSupport.mm +58 -0
  35. package/ios/YubikitYubiOtp.h +5 -0
  36. package/ios/YubikitYubiOtp.mm +120 -0
  37. package/lib/module/core.js +34 -0
  38. package/lib/module/core.js.map +1 -0
  39. package/lib/module/fido.js +40 -0
  40. package/lib/module/fido.js.map +1 -0
  41. package/lib/module/hooks/index.js +5 -0
  42. package/lib/module/hooks/index.js.map +1 -0
  43. package/lib/module/hooks/use-yubikey.js +12 -0
  44. package/lib/module/hooks/use-yubikey.js.map +1 -0
  45. package/lib/module/hooks/yubikey-provider.js +85 -0
  46. package/lib/module/hooks/yubikey-provider.js.map +1 -0
  47. package/lib/module/index.js +12 -0
  48. package/lib/module/index.js.map +1 -0
  49. package/lib/module/management.js +17 -0
  50. package/lib/module/management.js.map +1 -0
  51. package/lib/module/oath.js +53 -0
  52. package/lib/module/oath.js.map +1 -0
  53. package/lib/module/openpgp.js +89 -0
  54. package/lib/module/openpgp.js.map +1 -0
  55. package/lib/module/package.json +1 -0
  56. package/lib/module/piv.js +71 -0
  57. package/lib/module/piv.js.map +1 -0
  58. package/lib/module/specs/NativeYubikitCore.js +10 -0
  59. package/lib/module/specs/NativeYubikitCore.js.map +1 -0
  60. package/lib/module/specs/NativeYubikitFido.js +5 -0
  61. package/lib/module/specs/NativeYubikitFido.js.map +1 -0
  62. package/lib/module/specs/NativeYubikitManagement.js +5 -0
  63. package/lib/module/specs/NativeYubikitManagement.js.map +1 -0
  64. package/lib/module/specs/NativeYubikitOath.js +5 -0
  65. package/lib/module/specs/NativeYubikitOath.js.map +1 -0
  66. package/lib/module/specs/NativeYubikitOpenPgp.js +5 -0
  67. package/lib/module/specs/NativeYubikitOpenPgp.js.map +1 -0
  68. package/lib/module/specs/NativeYubikitPiv.js +5 -0
  69. package/lib/module/specs/NativeYubikitPiv.js.map +1 -0
  70. package/lib/module/specs/NativeYubikitSupport.js +5 -0
  71. package/lib/module/specs/NativeYubikitSupport.js.map +1 -0
  72. package/lib/module/specs/NativeYubikitYubiOtp.js +5 -0
  73. package/lib/module/specs/NativeYubikitYubiOtp.js.map +1 -0
  74. package/lib/module/support.js +11 -0
  75. package/lib/module/support.js.map +1 -0
  76. package/lib/module/types.js +2 -0
  77. package/lib/module/types.js.map +1 -0
  78. package/lib/module/yubiotp.js +32 -0
  79. package/lib/module/yubiotp.js.map +1 -0
  80. package/lib/typescript/package.json +1 -0
  81. package/lib/typescript/src/core.d.ts +14 -0
  82. package/lib/typescript/src/core.d.ts.map +1 -0
  83. package/lib/typescript/src/fido.d.ts +24 -0
  84. package/lib/typescript/src/fido.d.ts.map +1 -0
  85. package/lib/typescript/src/hooks/index.d.ts +3 -0
  86. package/lib/typescript/src/hooks/index.d.ts.map +1 -0
  87. package/lib/typescript/src/hooks/use-yubikey.d.ts +3 -0
  88. package/lib/typescript/src/hooks/use-yubikey.d.ts.map +1 -0
  89. package/lib/typescript/src/hooks/yubikey-provider.d.ts +23 -0
  90. package/lib/typescript/src/hooks/yubikey-provider.d.ts.map +1 -0
  91. package/lib/typescript/src/index.d.ts +10 -0
  92. package/lib/typescript/src/index.d.ts.map +1 -0
  93. package/lib/typescript/src/management.d.ts +8 -0
  94. package/lib/typescript/src/management.d.ts.map +1 -0
  95. package/lib/typescript/src/oath.d.ts +20 -0
  96. package/lib/typescript/src/oath.d.ts.map +1 -0
  97. package/lib/typescript/src/openpgp.d.ts +35 -0
  98. package/lib/typescript/src/openpgp.d.ts.map +1 -0
  99. package/lib/typescript/src/piv.d.ts +26 -0
  100. package/lib/typescript/src/piv.d.ts.map +1 -0
  101. package/lib/typescript/src/specs/NativeYubikitCore.d.ts +49 -0
  102. package/lib/typescript/src/specs/NativeYubikitCore.d.ts.map +1 -0
  103. package/lib/typescript/src/specs/NativeYubikitFido.d.ts +121 -0
  104. package/lib/typescript/src/specs/NativeYubikitFido.d.ts.map +1 -0
  105. package/lib/typescript/src/specs/NativeYubikitManagement.d.ts +53 -0
  106. package/lib/typescript/src/specs/NativeYubikitManagement.d.ts.map +1 -0
  107. package/lib/typescript/src/specs/NativeYubikitOath.d.ts +70 -0
  108. package/lib/typescript/src/specs/NativeYubikitOath.d.ts.map +1 -0
  109. package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts +53 -0
  110. package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts.map +1 -0
  111. package/lib/typescript/src/specs/NativeYubikitPiv.d.ts +47 -0
  112. package/lib/typescript/src/specs/NativeYubikitPiv.d.ts.map +1 -0
  113. package/lib/typescript/src/specs/NativeYubikitSupport.d.ts +49 -0
  114. package/lib/typescript/src/specs/NativeYubikitSupport.d.ts.map +1 -0
  115. package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts +45 -0
  116. package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts.map +1 -0
  117. package/lib/typescript/src/support.d.ts +6 -0
  118. package/lib/typescript/src/support.d.ts.map +1 -0
  119. package/lib/typescript/src/types.d.ts +293 -0
  120. package/lib/typescript/src/types.d.ts.map +1 -0
  121. package/lib/typescript/src/yubiotp.d.ts +13 -0
  122. package/lib/typescript/src/yubiotp.d.ts.map +1 -0
  123. package/package.json +181 -0
  124. package/src/core.ts +58 -0
  125. package/src/fido.ts +112 -0
  126. package/src/hooks/index.tsx +2 -0
  127. package/src/hooks/use-yubikey.tsx +10 -0
  128. package/src/hooks/yubikey-provider.tsx +146 -0
  129. package/src/index.tsx +10 -0
  130. package/src/management.ts +44 -0
  131. package/src/oath.ts +134 -0
  132. package/src/openpgp.ts +220 -0
  133. package/src/piv.ts +193 -0
  134. package/src/specs/NativeYubikitCore.ts +68 -0
  135. package/src/specs/NativeYubikitFido.ts +149 -0
  136. package/src/specs/NativeYubikitManagement.ts +78 -0
  137. package/src/specs/NativeYubikitOath.ts +110 -0
  138. package/src/specs/NativeYubikitOpenPgp.ts +148 -0
  139. package/src/specs/NativeYubikitPiv.ts +108 -0
  140. package/src/specs/NativeYubikitSupport.ts +61 -0
  141. package/src/specs/NativeYubikitYubiOtp.ts +82 -0
  142. package/src/support.ts +18 -0
  143. package/src/types.ts +404 -0
  144. 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
+ }