@pagopa/io-react-native-iso18013 0.3.0 → 0.5.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.
Files changed (110) hide show
  1. package/README.md +10 -5
  2. package/android/build.gradle +7 -1
  3. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeCborModule.kt +69 -134
  4. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeIso18013Module.kt +254 -183
  5. package/android/src/test/java/com/ioreactnativeiso18013/Base64UtilsTest.kt +66 -0
  6. package/android/src/test/java/com/ioreactnativeiso18013/IoReactNativeIso18013Test.kt +508 -0
  7. package/ios/Base64Utils.swift +10 -3
  8. package/ios/IoReactNativeCbor.mm +21 -21
  9. package/ios/IoReactNativeCbor.swift +116 -138
  10. package/ios/IoReactNativeIso18013.mm +10 -10
  11. package/ios/IoReactNativeIso18013.swift +172 -193
  12. package/lib/module/cbor/cbor/README.md +39 -59
  13. package/lib/module/cbor/cbor/decoder.js +13 -23
  14. package/lib/module/cbor/cbor/decoder.js.map +1 -1
  15. package/lib/module/cbor/cbor/error.js +15 -0
  16. package/lib/module/cbor/cbor/error.js.map +1 -0
  17. package/lib/module/cbor/cbor/index.js +1 -0
  18. package/lib/module/cbor/cbor/index.js.map +1 -1
  19. package/lib/module/cbor/cose/README.md +39 -9
  20. package/lib/module/cbor/cose/error.js +17 -0
  21. package/lib/module/cbor/cose/error.js.map +1 -0
  22. package/lib/module/cbor/cose/index.js +1 -0
  23. package/lib/module/cbor/cose/index.js.map +1 -1
  24. package/lib/module/cbor/cose/sign.js +4 -3
  25. package/lib/module/cbor/cose/sign.js.map +1 -1
  26. package/lib/module/iso18013/index.js +0 -1
  27. package/lib/module/iso18013/index.js.map +1 -1
  28. package/lib/module/iso18013/iso18013-5/README.md +120 -44
  29. package/lib/module/iso18013/iso18013-5/error.js +25 -0
  30. package/lib/module/iso18013/iso18013-5/error.js.map +1 -0
  31. package/lib/module/iso18013/iso18013-5/index.js +3 -2
  32. package/lib/module/iso18013/iso18013-5/index.js.map +1 -1
  33. package/lib/module/iso18013/iso18013-5/proximity.js +20 -15
  34. package/lib/module/iso18013/iso18013-5/proximity.js.map +1 -1
  35. package/lib/module/iso18013/iso18013-5/{schema.js → request.js} +1 -37
  36. package/lib/module/iso18013/iso18013-5/request.js.map +1 -0
  37. package/lib/module/iso18013/iso18013-7/README.md +66 -41
  38. package/lib/module/iso18013/iso18013-7/error.js +15 -0
  39. package/lib/module/iso18013/iso18013-7/error.js.map +1 -0
  40. package/lib/module/iso18013/iso18013-7/index.js +1 -0
  41. package/lib/module/iso18013/iso18013-7/index.js.map +1 -1
  42. package/lib/module/iso18013/iso18013-7/remote.js +11 -24
  43. package/lib/module/iso18013/iso18013-7/remote.js.map +1 -1
  44. package/lib/module/schema.js +46 -0
  45. package/lib/module/schema.js.map +1 -0
  46. package/lib/typescript/src/cbor/cbor/decoder.d.ts +12 -22
  47. package/lib/typescript/src/cbor/cbor/decoder.d.ts.map +1 -1
  48. package/lib/typescript/src/cbor/cbor/error.d.ts +68 -0
  49. package/lib/typescript/src/cbor/cbor/error.d.ts.map +1 -0
  50. package/lib/typescript/src/cbor/cbor/index.d.ts +1 -1
  51. package/lib/typescript/src/cbor/cbor/index.d.ts.map +1 -1
  52. package/lib/typescript/src/cbor/cose/error.d.ts +68 -0
  53. package/lib/typescript/src/cbor/cose/error.d.ts.map +1 -0
  54. package/lib/typescript/src/cbor/cose/index.d.ts +1 -1
  55. package/lib/typescript/src/cbor/cose/index.d.ts.map +1 -1
  56. package/lib/typescript/src/cbor/cose/sign.d.ts +4 -3
  57. package/lib/typescript/src/cbor/cose/sign.d.ts.map +1 -1
  58. package/lib/typescript/src/iso18013/index.d.ts +0 -1
  59. package/lib/typescript/src/iso18013/index.d.ts.map +1 -1
  60. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts +73 -0
  61. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts.map +1 -0
  62. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts +4 -3
  63. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts.map +1 -1
  64. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts +21 -14
  65. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts.map +1 -1
  66. package/lib/typescript/src/iso18013/iso18013-5/{schema.d.ts → request.d.ts} +1 -39
  67. package/lib/typescript/src/iso18013/iso18013-5/request.d.ts.map +1 -0
  68. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts +68 -0
  69. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts.map +1 -0
  70. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts +3 -2
  71. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts.map +1 -1
  72. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts +11 -25
  73. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts.map +1 -1
  74. package/lib/typescript/src/iso18013/types.d.ts +25 -0
  75. package/lib/typescript/src/iso18013/types.d.ts.map +1 -1
  76. package/lib/typescript/src/schema.d.ts +76 -0
  77. package/lib/typescript/src/schema.d.ts.map +1 -0
  78. package/package.json +1 -1
  79. package/src/cbor/cbor/README.md +39 -59
  80. package/src/cbor/cbor/decoder.ts +13 -23
  81. package/src/cbor/cbor/error.ts +23 -0
  82. package/src/cbor/cbor/index.ts +5 -1
  83. package/src/cbor/cose/README.md +39 -9
  84. package/src/cbor/cose/error.ts +23 -0
  85. package/src/cbor/cose/index.ts +5 -1
  86. package/src/cbor/cose/sign.ts +5 -4
  87. package/src/iso18013/index.ts +0 -7
  88. package/src/iso18013/iso18013-5/README.md +120 -44
  89. package/src/iso18013/iso18013-5/error.ts +35 -0
  90. package/src/iso18013/iso18013-5/index.ts +9 -8
  91. package/src/iso18013/iso18013-5/proximity.ts +21 -17
  92. package/src/iso18013/iso18013-5/{schema.ts → request.ts} +0 -42
  93. package/src/iso18013/iso18013-7/README.md +66 -41
  94. package/src/iso18013/iso18013-7/error.ts +21 -0
  95. package/src/iso18013/iso18013-7/index.ts +6 -5
  96. package/src/iso18013/iso18013-7/remote.ts +12 -34
  97. package/src/iso18013/types.ts +24 -0
  98. package/src/schema.ts +55 -0
  99. package/lib/module/cbor/cbor/failure.js +0 -2
  100. package/lib/module/cbor/cbor/failure.js.map +0 -1
  101. package/lib/module/cbor/cose/failure.js +0 -2
  102. package/lib/module/cbor/cose/failure.js.map +0 -1
  103. package/lib/module/iso18013/iso18013-5/schema.js.map +0 -1
  104. package/lib/typescript/src/cbor/cbor/failure.d.ts +0 -15
  105. package/lib/typescript/src/cbor/cbor/failure.d.ts.map +0 -1
  106. package/lib/typescript/src/cbor/cose/failure.d.ts +0 -15
  107. package/lib/typescript/src/cbor/cose/failure.d.ts.map +0 -1
  108. package/lib/typescript/src/iso18013/iso18013-5/schema.d.ts.map +0 -1
  109. package/src/cbor/cbor/failure.ts +0 -18
  110. package/src/cbor/cose/failure.ts +0 -20
package/README.md CHANGED
@@ -10,12 +10,17 @@ npm install @pagopa/io-react-native-iso18013
10
10
 
11
11
  ## Usage
12
12
 
13
- Each module is documented in its own README file:
13
+ This library includes two native modules for both iOS and Android:
14
14
 
15
- - [ISO18013-5](src/iso18013/iso18013-5/README.md): Proximity presentation according to the ISO 18013-5 standard;
16
- - [ISO18013-7](src/iso18013/iso18013-7/README.md): Remote presentation according to the ISO 18013-7 standard;
17
- - [CBOR](src/cbor/cbor/README.md): Decoding of CBOR data into readable objects;
18
- - [COSE](src/cbor/cose/README.md): Management of COSE verify and sign operations.
15
+ - [IoReactNativeIso18013](src/iso18013/iso18013-5/proximity.ts) for ISO 18013-5 and ISO 18013-7 implementations;
16
+ - [IoReactNativeCbor](src/cbor/cbor.ts) for CBOR and COSE implementations.
17
+
18
+ On the javascript side, the library exposes the following modules:
19
+
20
+ - [ISO18013-5](src/iso18013/iso18013-5/README.md): Proximity presentation according to the ISO 18013-5 standard which is part of the `IoReactNativeIso18013` module;
21
+ - [ISO18013-7](src/iso18013/iso18013-7/README.md): Remote presentation according to the ISO 18013-7 standard which is part of the `IoReactNativeIso18013` module;
22
+ - [CBOR](src/cbor/cbor/README.md): Decoding of CBOR data into readable objects which is part of the `IoReactNativeCbor` module;
23
+ - [COSE](src/cbor/cose/README.md): Management of COSE verify and sign operations which is part of the `IoReactNativeCbor` module.
19
24
 
20
25
  ## Contributing
21
26
 
@@ -65,6 +65,12 @@ android {
65
65
  sourceCompatibility JavaVersion.VERSION_1_8
66
66
  targetCompatibility JavaVersion.VERSION_1_8
67
67
  }
68
+
69
+ testOptions {
70
+ unitTests.all {
71
+ useJUnit()
72
+ }
73
+ }
68
74
  }
69
75
 
70
76
  repositories {
@@ -79,5 +85,5 @@ dependencies {
79
85
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
80
86
  implementation "it.pagopa.io.wallet.proximity:proximity:2.1.0"
81
87
  implementation "it.pagopa.io.wallet.cbor:cbor:1.3.0"
88
+ testImplementation('junit:junit:4.13.2')
82
89
  }
83
-
@@ -5,10 +5,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
5
  import com.facebook.react.bridge.ReactMethod
6
6
  import com.facebook.react.bridge.Promise
7
7
  import com.facebook.react.bridge.ReadableMap
8
- import com.facebook.react.bridge.WritableMap
9
- import com.facebook.react.bridge.WritableNativeMap
10
8
  import it.pagopa.io.wallet.cbor.cose.COSEManager
11
- import it.pagopa.io.wallet.cbor.cose.FailureReason
12
9
  import it.pagopa.io.wallet.cbor.cose.SignWithCOSEResult
13
10
  import it.pagopa.io.wallet.cbor.parser.CBorParser
14
11
 
@@ -19,125 +16,87 @@ class IoReactNativeCborModule(reactContext: ReactApplicationContext) :
19
16
  return NAME
20
17
  }
21
18
 
19
+ /**
20
+ * Decode base64 or base64url encoded CBOR data to JSON object.
21
+ * Resolves with a string containing the parsed data or rejects with an error code
22
+ * defined in [ModuleErrorCodes].
23
+ * This method does not handle nested CBOR data, which will need additional parsing.
24
+ * @param data the base64 or base64url encoded CBOR string
25
+ */
22
26
  @ReactMethod
23
27
  fun decode(data: String, promise: Promise) {
24
- val buffer = try {
25
- Base64Utils.decodeBase64AndBase64Url(data)
26
- } catch (e: Exception) {
27
- ModuleException.INVALID_ENCODING.reject(
28
- promise,
29
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
30
- )
31
- return;
32
- }
33
-
34
28
  try {
35
- CBorParser(buffer).toJson()?.let {
36
- promise.resolve(it)
37
- } ?: run {
38
- ModuleException.UNABLE_TO_DECODE.reject(promise)
39
- }
29
+ val buffer = Base64Utils.decodeBase64AndBase64Url(data)
30
+ val result = CBorParser(buffer).toJson()
31
+ promise.resolve(result)
40
32
  } catch (e: Exception) {
41
- ModuleException.UNKNOWN_EXCEPTION.reject(
42
- promise,
43
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
44
- )
33
+ promise.reject(ModuleErrorCodes.DECODE_ERROR, e.message, e)
45
34
  }
46
35
  }
47
36
 
37
+ /**
38
+ * Decode base64 or base64url encoded mDOC-CBOR data to a JSON object.
39
+ * Resolves with a string containing the parsed data or rejects with an error code
40
+ * @param data the base64 or base64url encoded mDOC-CBOR string
41
+ */
48
42
  @ReactMethod
49
43
  fun decodeDocuments(data: String, promise: Promise) {
50
- val buffer = try {
51
- Base64Utils.decodeBase64AndBase64Url(data)
52
- } catch (e: Exception) {
53
- ModuleException.INVALID_ENCODING.reject(
54
- promise,
55
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
56
- )
57
- return;
58
- }
59
44
  try {
45
+ val buffer = Base64Utils.decodeBase64AndBase64Url(data)
60
46
  CBorParser(buffer).documentsCborToJson(separateElementIdentifier = true, onComplete = {
61
47
  promise.resolve(it)
62
- }) { ex ->
63
- ModuleException.UNABLE_TO_DECODE.reject(
64
- promise,
65
- Pair(ERROR_USER_INFO_KEY, ex.message.orEmpty())
66
- )
67
- }
48
+ }, onError = { e ->
49
+ promise.reject(ModuleErrorCodes.DECODE_DOCUMENTS_ERROR, e.message, e)
50
+ })
68
51
  } catch (e: Exception) {
69
- ModuleException.UNKNOWN_EXCEPTION.reject(
70
- promise,
71
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
72
- )
52
+ promise.reject(ModuleErrorCodes.DECODE_DOCUMENTS_ERROR, e.message, e)
73
53
  }
74
54
  }
75
55
 
56
+ /**
57
+ * Decode base64 or base64url encoded issuerSigned attribute part of an mDOC-CBOR.
58
+ * @param data the base64 or base64url encoded mDOC-CBOR containing the issuerSigned data string
59
+ * Resolves with a string containing the parsed data or rejects with an error code
60
+ * defined in [ModuleErrorCodes].
61
+ */
76
62
  @ReactMethod
77
- fun decodeIssuerSigned(issuerSigned: String, promise: Promise) {
78
- val buffer = try {
79
- Base64Utils.decodeBase64AndBase64Url(issuerSigned)
80
- } catch (e: Exception) {
81
- ModuleException.INVALID_ENCODING.reject(
82
- promise,
83
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
84
- )
85
- return;
86
- }
63
+ fun decodeIssuerSigned(data: String, promise: Promise) {
87
64
  try {
88
- CBorParser(buffer).issuerSignedCborToJson(separateElementIdentifier = true).let {
89
- if (it == null) {
90
- ModuleException.UNABLE_TO_DECODE.reject(
91
- promise,
92
- Pair(ERROR_USER_INFO_KEY, "Unable to decode passed CBOR")
65
+ val buffer =
66
+ Base64Utils.decodeBase64AndBase64Url(data)
67
+ val result =
68
+ CBorParser(buffer).issuerSignedCborToJson(separateElementIdentifier = true) ?: run {
69
+ // We don't have the exact error here for some reason
70
+ promise.reject(
71
+ ModuleErrorCodes.DECODE_ISSUER_SIGNED_ERROR,
72
+ "An error occurred while decoding the issuer signed content"
93
73
  )
94
- return
95
74
  }
96
- promise.resolve(it)
97
- }
75
+ promise.resolve(result)
98
76
  } catch (e: Exception) {
99
- ModuleException.UNKNOWN_EXCEPTION.reject(
100
- promise,
101
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
102
- )
77
+ promise.reject(ModuleErrorCodes.DECODE_ISSUER_SIGNED_ERROR, e.message, e)
103
78
  }
104
79
  }
105
80
 
81
+ /**
82
+ * Sign base64 encoded data with COSE and return the COSE-Sign1 object in base64 encoding.
83
+ * Resolves with a string containing the COSE-Sign1 object in base64 encoding or rejects with an
84
+ * error code defined in [ModuleErrorCodes].
85
+ * @param data the base64 or base64url encoded payload to sign
86
+ * @param keyTag the alias of the key to use for signing.
87
+ */
106
88
  @ReactMethod
107
- fun sign(payload: String, keyTag: String, promise: Promise) {
108
- val data = try {
109
- Base64Utils.decodeBase64AndBase64Url(payload)
110
- } catch (e: Exception) {
111
- ModuleException.INVALID_ENCODING.reject(
112
- promise,
113
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
114
- )
115
- return;
116
- }
117
-
89
+ fun sign(data: String, keyTag: String, promise: Promise) {
118
90
  try {
91
+ val buffer = Base64Utils.decodeBase64AndBase64Url(data)
119
92
  val result = COSEManager().signWithCOSE(
120
- data = data,
93
+ data = buffer,
121
94
  alias = keyTag
122
95
  )
123
96
  when (result) {
124
97
  is SignWithCOSEResult.Failure -> {
125
- when (result.reason) {
126
- FailureReason.NO_KEY -> ModuleException.PUBLIC_KEY_NOT_FOUND.reject(
127
- promise,
128
- Pair(ERROR_USER_INFO_KEY, result.reason.msg)
129
- )
130
-
131
- FailureReason.FAIL_TO_SIGN -> ModuleException.UNABLE_TO_SIGN.reject(
132
- promise,
133
- Pair(ERROR_USER_INFO_KEY, result.reason.msg)
134
- )
135
-
136
- else -> ModuleException.UNKNOWN_EXCEPTION.reject(
137
- promise,
138
- Pair(ERROR_USER_INFO_KEY, result.reason.msg)
139
- )
140
- }
98
+ // We don't have a throwable to pass here from the onError callback
99
+ promise.reject(ModuleErrorCodes.SIGN_ERROR, result.reason.msg)
141
100
  }
142
101
 
143
102
  is SignWithCOSEResult.Success -> {
@@ -145,65 +104,41 @@ class IoReactNativeCborModule(reactContext: ReactApplicationContext) :
145
104
  }
146
105
  }
147
106
  } catch (e: Exception) {
148
- ModuleException.UNKNOWN_EXCEPTION.reject(
149
- promise,
150
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
151
- )
107
+ promise.reject(ModuleErrorCodes.SIGN_ERROR, e.message, e)
152
108
  }
153
109
  }
154
110
 
111
+ /**
112
+ * Verifies a COSE-Sign1 object with the provided public key.
113
+ * Resolves with a boolean indicating whether or not the verification succeeded or not or rejects
114
+ * with an error code defined in [ModuleErrorCodes].
115
+ * @param data the COSE-Sign1 object in base64 or base64url encoding
116
+ * @param publicKey the public key in JWK format
117
+ */
155
118
  @ReactMethod
156
- fun verify(sign1Data: String, publicKey: ReadableMap, promise: Promise) {
157
- val data = try {
158
- Base64Utils.decodeBase64AndBase64Url(sign1Data)
159
- } catch (e: Exception) {
160
- ModuleException.INVALID_ENCODING.reject(
161
- promise,
162
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
163
- )
164
- return;
165
- }
166
-
119
+ fun verify(data: String, publicKey: ReadableMap, promise: Promise) {
167
120
  try {
121
+ val buffer = Base64Utils.decodeBase64AndBase64Url(data)
168
122
  val result = COSEManager().verifySign1FromJWK(
169
- dataSigned = data,
123
+ dataSigned = buffer,
170
124
  jwk = publicKey.toString()
171
125
  )
172
126
  promise.resolve(result)
173
127
  } catch (e: Exception) {
174
- ModuleException.UNKNOWN_EXCEPTION.reject(
175
- promise,
176
- Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
177
- )
128
+ promise.reject(ModuleErrorCodes.VERIFY_ERROR, e.message, e)
178
129
  }
179
130
  }
180
131
 
181
132
  companion object {
182
133
  const val NAME = "IoReactNativeCbor"
183
- const val ERROR_USER_INFO_KEY = "error"
184
-
185
- private enum class ModuleException(
186
- val ex: Exception
187
- ) {
188
- UNABLE_TO_DECODE(Exception("UNABLE_TO_DECODE")),
189
- PUBLIC_KEY_NOT_FOUND(Exception("PUBLIC_KEY_NOT_FOUND")),
190
- UNABLE_TO_SIGN(Exception("UNABLE_TO_SIGN")),
191
- INVALID_ENCODING(Exception("INVALID_ENCODING")),
192
- UNKNOWN_EXCEPTION(Exception("UNKNOWN_EXCEPTION"));
193
134
 
194
- fun reject(
195
- promise: Promise, vararg args: Pair<String, String>
196
- ) {
197
- exMap(*args).let {
198
- promise.reject(it.first, ex.message, it.second)
199
- }
200
- }
201
-
202
- private fun exMap(vararg args: Pair<String, String>): Pair<String, WritableMap> {
203
- val writableMap = WritableNativeMap()
204
- args.forEach { writableMap.putString(it.first, it.second) }
205
- return Pair(this.ex.message ?: "UNKNOWN", writableMap)
206
- }
135
+ // Errors which this module uses to reject a promise
136
+ private object ModuleErrorCodes {
137
+ const val DECODE_ERROR = "DECODE_ERROR"
138
+ const val DECODE_DOCUMENTS_ERROR = "DECODE_DOCUMENTS_ERROR"
139
+ const val DECODE_ISSUER_SIGNED_ERROR = "DECODE_ISSUER_SIGNED_ERROR"
140
+ const val SIGN_ERROR = "SIGN_ERROR"
141
+ const val VERIFY_ERROR = "VERIFY_ERROR"
207
142
  }
208
143
  }
209
144
  }