@pagopa/io-react-native-iso18013 0.4.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 (54) 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 +90 -58
  4. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeIso18013Module.kt +216 -100
  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/IoReactNativeCbor.mm +21 -21
  8. package/ios/IoReactNativeCbor.swift +70 -22
  9. package/ios/IoReactNativeIso18013.mm +10 -10
  10. package/ios/IoReactNativeIso18013.swift +89 -81
  11. package/lib/module/cbor/cbor/README.md +11 -63
  12. package/lib/module/cbor/cbor/decoder.js +13 -23
  13. package/lib/module/cbor/cbor/decoder.js.map +1 -1
  14. package/lib/module/cbor/cose/README.md +1 -1
  15. package/lib/module/cbor/cose/sign.js +4 -3
  16. package/lib/module/cbor/cose/sign.js.map +1 -1
  17. package/lib/module/iso18013/iso18013-5/README.md +66 -26
  18. package/lib/module/iso18013/iso18013-5/index.js.map +1 -1
  19. package/lib/module/iso18013/iso18013-5/proximity.js +19 -6
  20. package/lib/module/iso18013/iso18013-5/proximity.js.map +1 -1
  21. package/lib/module/iso18013/iso18013-5/request.js +0 -17
  22. package/lib/module/iso18013/iso18013-5/request.js.map +1 -1
  23. package/lib/module/iso18013/iso18013-7/README.md +32 -36
  24. package/lib/module/iso18013/iso18013-7/remote.js +11 -12
  25. package/lib/module/iso18013/iso18013-7/remote.js.map +1 -1
  26. package/lib/typescript/src/cbor/cbor/decoder.d.ts +12 -22
  27. package/lib/typescript/src/cbor/cbor/decoder.d.ts.map +1 -1
  28. package/lib/typescript/src/cbor/cose/sign.d.ts +4 -3
  29. package/lib/typescript/src/cbor/cose/sign.d.ts.map +1 -1
  30. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts +2 -2
  31. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts.map +1 -1
  32. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts +20 -8
  33. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts.map +1 -1
  34. package/lib/typescript/src/iso18013/iso18013-5/request.d.ts +0 -23
  35. package/lib/typescript/src/iso18013/iso18013-5/request.d.ts.map +1 -1
  36. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts +1 -1
  37. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts.map +1 -1
  38. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts +11 -11
  39. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts.map +1 -1
  40. package/lib/typescript/src/iso18013/types.d.ts +25 -0
  41. package/lib/typescript/src/iso18013/types.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/cbor/cbor/README.md +11 -63
  44. package/src/cbor/cbor/decoder.ts +13 -23
  45. package/src/cbor/cose/README.md +1 -1
  46. package/src/cbor/cose/sign.ts +5 -4
  47. package/src/iso18013/iso18013-5/README.md +66 -26
  48. package/src/iso18013/iso18013-5/index.ts +2 -6
  49. package/src/iso18013/iso18013-5/proximity.ts +20 -8
  50. package/src/iso18013/iso18013-5/request.ts +0 -22
  51. package/src/iso18013/iso18013-7/README.md +32 -36
  52. package/src/iso18013/iso18013-7/index.ts +1 -1
  53. package/src/iso18013/iso18013-7/remote.ts +12 -14
  54. package/src/iso18013/types.ts +24 -0
@@ -5,14 +5,24 @@ import CryptoKit
5
5
  @objc(IoReactNativeCbor)
6
6
  class IoReactNativeCbor: NSObject {
7
7
 
8
- @objc func decode(
9
- _ cbor: String,
8
+ /**
9
+ Decode base64 or base64url encoded CBOR data to JSON object.
10
+ Resolves with a string containing the parsed data or rejects with an error code defined in ``ModuleErrorCodes``.
11
+ This method does not handle nested CBOR data, which will need additional parsing.
12
+ - Parameters:
13
+ - data: The base64 or base64url encoded CBOR string.
14
+ - resolve: The promise to be resolved.
15
+ - reject: The promise to be rejected.
16
+ */
17
+ @objc(decode:withResolver:withRejecter:)
18
+ func decode(
19
+ data: String,
10
20
  resolver resolve: RCTPromiseResolveBlock,
11
21
  rejecter reject: RCTPromiseRejectBlock
12
22
  ) {
13
23
  do{
14
- let data = try Base64Utils.decodeBase64OrBase64URL(base: cbor)
15
- guard let json = CborCose.jsonFromCBOR(data: data) else {
24
+ let buffer = try Base64Utils.decodeBase64OrBase64URL(base: data)
25
+ guard let json = CborCose.jsonFromCBOR(data: buffer) else {
16
26
  // We don't have the exact error here as this method returns nil upon failure
17
27
  reject(ModuleErrorCodes.decodeError.rawValue, "Unable to decode CBOR", nil)
18
28
  return
@@ -24,14 +34,23 @@ class IoReactNativeCbor: NSObject {
24
34
  }
25
35
  }
26
36
 
27
- @objc func decodeDocuments(
28
- _ mdoc: String,
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 defined in ``ModuleErrorCodes``.
40
+ - Parameters:
41
+ - data: The base64 or base64url encoded mDOC-CBOR string.
42
+ - resolve: The promise to be resolved.
43
+ - reject: The promise to be rejected.
44
+ */
45
+ @objc(decodeDocuments:withResolver:withRejecter:)
46
+ func decodeDocuments(
47
+ data: String,
29
48
  resolver resolve: RCTPromiseResolveBlock,
30
49
  rejecter reject: RCTPromiseRejectBlock
31
50
  ) {
32
51
  do{
33
- let data = try Base64Utils.decodeBase64OrBase64URL(base: mdoc)
34
- guard let json = CborCose.decodeCBOR(data: data, true, true) else {
52
+ let buffer = try Base64Utils.decodeBase64OrBase64URL(base: data)
53
+ guard let json = CborCose.decodeCBOR(data: buffer, true, true) else {
35
54
  // We don't have the exact error here as this method returns nil upon failure
36
55
  reject(ModuleErrorCodes.decodeDocumentsError.rawValue, "Unable to decode document CBOR", nil)
37
56
  return
@@ -42,14 +61,23 @@ class IoReactNativeCbor: NSObject {
42
61
  }
43
62
  }
44
63
 
45
- @objc func decodeIssuerSigned(
46
- _ issuerSigned: String,
64
+ /**
65
+ Decode base64 or base64url encoded issuerSigned attribute part of an mDOC-CBOR.
66
+ Resolves with a string containing the parsed data or rejects with an error code defined in ``ModuleErrorCodes``.
67
+ - Parameters:
68
+ - data: The base64 or base64url encoded mDOC-CBOR containing the issuerSigned data string.
69
+ - resolve: The promise to be resolved.
70
+ - reject: The promise to be rejected.
71
+ */
72
+ @objc(decodeIssuerSigned:withResolver:withRejecter:)
73
+ func decodeIssuerSigned(
74
+ data: String,
47
75
  resolver resolve: RCTPromiseResolveBlock,
48
76
  rejecter reject: RCTPromiseRejectBlock
49
77
  ) {
50
78
  do{
51
- let data = try Base64Utils.decodeBase64OrBase64URL(base: issuerSigned)
52
- guard let json = CborCose.issuerSignedCborToJson(data: data) else {
79
+ let buffer = try Base64Utils.decodeBase64OrBase64URL(base: data)
80
+ guard let json = CborCose.issuerSignedCborToJson(data: buffer) else {
53
81
  // We don't have the exact error here as this method returns nil upon failure
54
82
  reject(ModuleErrorCodes.decodeIssuerSignedError.rawValue, "Unable to decode Issuer Signed CBOR", nil)
55
83
  return
@@ -60,8 +88,18 @@ class IoReactNativeCbor: NSObject {
60
88
  }
61
89
  }
62
90
 
63
- @objc func sign(
64
- _ payloadData: String,
91
+ /**
92
+ Sign base64 encoded data with COSE and return the COSE-Sign1 object in base64 encoding.
93
+ Resolves with a string containing the COSE-Sign1 object in base64 encoding or rejects with an error code defined in ``ModuleErrorCodes``.
94
+ - Parameters:
95
+ - data: The base64 or base64url encoded payload to sign.
96
+ - keyTag: The alias of the key to use for signing.
97
+ - resolve: The promise to be resolved.
98
+ - reject: The promise to be rejected.
99
+ */
100
+ @objc(sign:withKeyTag:withResolver:withRejecter:)
101
+ func sign(
102
+ data: String,
65
103
  keyTag: String,
66
104
  resolver resolve: @escaping RCTPromiseResolveBlock,
67
105
  rejecter reject: @escaping RCTPromiseRejectBlock
@@ -73,13 +111,13 @@ class IoReactNativeCbor: NSObject {
73
111
  }
74
112
 
75
113
  do{
76
- let data = try Base64Utils.decodeBase64OrBase64URL(base: payloadData)
114
+ let buffer = try Base64Utils.decodeBase64OrBase64URL(base: data)
77
115
  guard let coseKey = CoseKeyPrivate(crv: .p256, keyTag: keyTag) else {
78
116
  // We don't have the exact error here as this method returns nil upon failure
79
117
  reject(ModuleErrorCodes.signError.rawValue, "Unable to create a private key with the given keytag: \(keyTag)", nil)
80
118
  return
81
119
  }
82
- let signedPayload = CborCose.sign(data: data, privateKey: coseKey)
120
+ let signedPayload = CborCose.sign(data: buffer, privateKey: coseKey)
83
121
  resolve(signedPayload.base64EncodedString())
84
122
  }
85
123
  catch{
@@ -88,18 +126,28 @@ class IoReactNativeCbor: NSObject {
88
126
  }
89
127
  }
90
128
 
91
- @objc func verify(
92
- _ sign1Data: String,
93
- jwk: NSDictionary,
129
+ /**
130
+ Verifies a COSE-Sign1 object with the provided public key.
131
+ Resolves with boolean indicating whether or not the verification succeeded or not or rejects with an error code defined in ``ModuleErrorCodes``.
132
+ - Parameters:
133
+ - data: The COSE-Sign1 object in base64 or base64url encoding.
134
+ - publicKey: The public key in JWK format.
135
+ - resolve: The promise to be resolved
136
+ - reject: The promise to be rejected..
137
+ */
138
+ @objc(verify:withJwk:withResolver:withRejecter:)
139
+ func verify(
140
+ data: String,
141
+ publicKey: NSDictionary,
94
142
  resolver resolve: RCTPromiseResolveBlock,
95
143
  rejecter reject: RCTPromiseRejectBlock
96
144
  ) {
97
145
  do {
98
- let data = try Base64Utils.decodeBase64OrBase64URL(base: sign1Data)
99
- let publicKeyJson = try JSONSerialization.data(withJSONObject: jwk, options:[] )
146
+ let buffer = try Base64Utils.decodeBase64OrBase64URL(base: data)
147
+ let publicKeyJson = try JSONSerialization.data(withJSONObject: publicKey, options:[] )
100
148
  let publicKeyString = String(data: publicKeyJson, encoding: .utf8)!
101
149
  let publicKey = CoseKey(jwk: publicKeyString)!
102
- let verified = CborCose.verify(data: data, publicKey: publicKey)
150
+ let verified = CborCose.verify(data: buffer, publicKey: publicKey)
103
151
  resolve(verified)
104
152
  } catch {
105
153
  reject(ModuleErrorCodes.verifyError.rawValue, error.localizedDescription, error)
@@ -18,22 +18,22 @@ RCT_EXTERN_METHOD(generateResponse:(NSArray *)documents
18
18
  withResolver:(RCTPromiseResolveBlock)resolve
19
19
  withRejecter:(RCTPromiseRejectBlock)reject)
20
20
 
21
- RCT_EXTERN_METHOD(sendResponse:(NSString)response
21
+ RCT_EXTERN_METHOD(sendResponse:(NSString *)response
22
22
  withResolver:(RCTPromiseResolveBlock)resolve
23
23
  withRejecter:(RCTPromiseRejectBlock)reject)
24
24
 
25
- RCT_EXTERN_METHOD(sendErrorResponse:(NSInteger)status
25
+ RCT_EXTERN_METHOD(sendErrorResponse:(NSInteger *)code
26
26
  withResolver:(RCTPromiseResolveBlock)resolve
27
27
  withRejecter:(RCTPromiseRejectBlock)reject)
28
28
 
29
- RCT_EXTERN_METHOD(generateOID4VPDeviceResponse: (NSString)clientId
30
- responseUri: (NSString*)responseUri
31
- authorizationRequestNonce: (NSString*)authorizationRequestNonce
32
- mdocGeneratedNonce: (NSString*)mdocGeneratedNonce
33
- documents: (NSArray*)documents
34
- fieldRequestedAndAccepted: (NSString*)fieldRequestedAndAccepted
35
- resolver: (RCTPromiseResolveBlock)resolve
36
- rejecter: (RCTPromiseRejectBlock)reject)
29
+ RCT_EXTERN_METHOD(generateOID4VPDeviceResponse: (NSString *)clientId
30
+ withResponseUri: (NSString *)responseUri
31
+ withAuthorizationRequestNonce: (NSString *)authorizationRequestNonce
32
+ withMdocGeneratedNonce: (NSString *)mdocGeneratedNonce
33
+ withDocuments: (NSArray *)documents
34
+ withAcceptedFields: (NSDictionary *)acceptedFields
35
+ withResolver: (RCTPromiseResolveBlock)resolve
36
+ withRejecter: (RCTPromiseRejectBlock)reject)
37
37
 
38
38
  + (BOOL)requiresMainQueueSetup
39
39
  {
@@ -37,8 +37,7 @@ class IoReactNativeIso18013: RCTEventEmitter {
37
37
 
38
38
  /**
39
39
  Starts the proximity flow by allocating the necessary resources and initializing the Bluetooth stack.
40
- Resolves to true or rejects if an error occurs.
41
-
40
+ Resolves to true or rejects with an error code defined in ``ModuleErrorCodes``.
42
41
  - Parameters:
43
42
  - certificates: Two-dimensional array of base64 strings representing DER encoded X.509 certificate which are used to authenticate the verifier app
44
43
  - resolve: The promise to be resolved
@@ -47,7 +46,7 @@ class IoReactNativeIso18013: RCTEventEmitter {
47
46
  @objc(start:withResolver:withRejecter:)
48
47
  func start(
49
48
  certificates: [Any],
50
- _ resolve: @escaping RCTPromiseResolveBlock,
49
+ resolve: @escaping RCTPromiseResolveBlock,
51
50
  reject: @escaping RCTPromiseRejectBlock
52
51
  ){
53
52
  do {
@@ -65,10 +64,9 @@ class IoReactNativeIso18013: RCTEventEmitter {
65
64
 
66
65
  /**
67
66
  Utility function to parse an array coming from the React Native Bridge into an array of Data representing DER encoded X.509 certificates.
68
-
69
67
  - Parameters:
70
- - certificates:Two-dimensional array of base64 strings representing DER encoded X.509 certificate
71
-
68
+ - certificates: Two-dimensional array of base64 strings representing DER encoded X.509 certificate
69
+ - Throws: `ParsingError` if the provided certificate is not a valid base64 encoded string.
72
70
  - Returns: A two-dimensional array of Data containing DER encoded X.509 certificates.
73
71
  */
74
72
  private func parseCertificates(_ certificates: [Any]) throws -> [[Data]] {
@@ -87,15 +85,14 @@ class IoReactNativeIso18013: RCTEventEmitter {
87
85
 
88
86
  /**
89
87
  Creates a QR code to be scanned in order to initialize the presentation.
90
- Resolves with the QR code strings.
91
-
88
+ Resolves with a string containing the QR code or rejects with an error code defined in ``ModuleErrorCodes``.
92
89
  - Parameters:
93
90
  - resolve: The promise to be resolved
94
91
  - reject: The promise to be rejected
95
- */
92
+ */
96
93
  @objc(getQrCodeString:withRejecter:)
97
94
  func getQrCodeString(
98
- _ resolve: @escaping RCTPromiseResolveBlock,
95
+ resolve: @escaping RCTPromiseResolveBlock,
99
96
  reject: @escaping RCTPromiseRejectBlock
100
97
  ) {
101
98
  do{
@@ -110,20 +107,17 @@ class IoReactNativeIso18013: RCTEventEmitter {
110
107
  Parses an array of documents from the React Native bridge which doesn't have any typing to an array of ``IOWalletProximity.ProximityDocument``.
111
108
  It checks if each element in the array has `issuerSignedContent`, `alias` and `docType` properties in order to build a ``IOWalletProximity.ProximityDocument``, then it appens it to the array.
112
109
  The result can be fed to ``IOWalletProximity.generateResponse``.
113
-
114
110
  - Parameters:
115
111
  - documents: An array containing documents. Each document is defined as a map containing:
116
112
  - issuerSignedContent which is a base64 or base64url encoded string representing the credential;
117
113
  - alias which is the alias of the key used to sign the credential;
118
114
  - docType which is the document type.
119
-
120
115
  - Throws: `ParsingError`:
121
116
  - If the provided documents array do not contain a dictionary;
122
117
  - If the provided dictionary doesn't adhere to the structure we expect;
123
118
  - If the issuerSignedContent is not a valid base64 or base64url encoded string;
124
119
  - If the creation of a ProximityDdocument fails.
125
-
126
- - Returns: An array of `ProximityDocument` containg the documents to be presented
120
+ - Returns: An array of `ProximityDocument` containg the documents to be presented.
127
121
  */
128
122
  private func parseDocuments(documents: [Any]) throws -> [ProximityDocument] {
129
123
  return try documents.map{ (element) -> ProximityDocument in
@@ -151,14 +145,10 @@ class IoReactNativeIso18013: RCTEventEmitter {
151
145
  Parses a dictionary of accepted fields for the presentation from the React Native bridge which doesn't have any typing to a ``AcceptedFieldsDict`` dictionary.
152
146
  It checks if each element in the array is a dictionary where the key is a string, and the value is another dictionary. This nested dictionary has a string as its key and a boolean as its value, then it appens it to the array.
153
147
  The result can be fed to ``IOWalletProximity.generateResponse``.
154
-
155
148
  - Parameters:
156
- - acceptedFields: A dictionary of any elements. In order to be added to the result dictionary each element must be shaped as ``AcceptedFieldsDict`` thus as [String: [String: [String: Bool]]]
157
-
158
- - Throws: `ParsingError` if a value doesn't has the ``AcceptedFieldsDict`` shape or the result dictionary is empty
159
-
160
- - Returns: An ``AcceptedFieldsDict`` containg the accepted fields to be presented
161
-
149
+ - acceptedFields: A dictionary of any elements. In order to be added to the result dictionary each element must be shaped as ``AcceptedFieldsDict`` thus as [String: [String: [String: Bool]]].
150
+ - Throws: `ParsingError` if a value doesn't has the ``AcceptedFieldsDict`` shape or the result dictionary is empty.
151
+ - Returns: An ``AcceptedFieldsDict`` containg the accepted fields to be presented.
162
152
  */
163
153
  private func parseAcceptedFields(acceptedFields: [AnyHashable: Any]) throws(ParsingError) -> AcceptedFieldsDict {
164
154
  var result: AcceptedFieldsDict = [:]
@@ -173,50 +163,40 @@ class IoReactNativeIso18013: RCTEventEmitter {
173
163
  result[keyString] = valueDict
174
164
  }
175
165
 
176
- if(result.isEmpty){
177
- throw ParsingError.acceptedFieldsNotValid("Empty accepted fields cannot be empty")
178
- }
179
-
180
166
  return result
181
167
  }
182
168
 
183
169
  /**
184
- Generates a response containing the documents and the fields which the user decided to present.
185
- It parses the untyped ``documents`` and ``acceptedFields`` parameters and feeds them to the ``IOWalletProximity.generateDeviceResponse`` function.
186
- It resolves the promise with the response as a base64 encoded string.
187
- It rejects the promise if an error occurs during the parameters parsing or while generating the device response.
188
-
189
- - Parameters:
190
- - documents: An array containing documents. Each document is defined as a map containing:
191
- - issuerSignedContent which is a base64 or base64url encoded string representing the credential;
192
- - alias which is the alias of the key used to sign the credential;
193
- - docType which is the document type.
194
- - issuerSignedContent which is a base64 or base64url encoded string representing the credential;
195
- - alias which is the alias of the key used to sign the credential;
196
- - docType which is the document type.
197
- - acceptedFields: A dictionary of elements, where each element must adhere to the structure of AcceptedFieldsDict—specifically, a [String: [String: [String: Bool]]]. The outermost key represents the credentia doctypel. The inner dictionary contains namespaces, and for each namespace, there is another dictionary mapping requested claims to a boolean value, which indicates whether the user is willing to present the corresponding claim. Example:
170
+ Generates a response containing the documents and the fields which the user decided to present.
171
+ It parses the untyped ``documents`` and ``acceptedFields`` parameters and feeds them to the ``IOWalletProximity.generateDeviceResponse`` function.
172
+ Resolves with a base64 encoded response or rejects with an error code defined in ``ModuleErrorCodes``.
173
+ - Parameters:
174
+ - documents: An array containing documents. Each document is defined as a map containing:
175
+ - issuerSignedContent which is a base64 or base64url encoded string representing the credential;
176
+ - alias which is the alias of the key used to sign the credential;
177
+ - docType which is the document type.
178
+ - acceptedFields: A dictionary of elements, where each element must adhere to the structure of AcceptedFieldsDict—specifically, a [String: [String: [String: Bool]]]. The outermost key represents the credential doctype. The inner dictionary contains namespaces, and for each namespace, there is another dictionary mapping requested claims to a boolean value, which indicates whether the user is willing to present the corresponding claim. Example:
198
179
 
199
180
 
200
- {
201
- "org.iso.18013.5.1.mDL": {
202
- "org.iso.18013.5.1": {
203
- "hair_colour": true,
204
- "given_name_national_character": true,
205
- "family_name_national_character": true,
206
- "given_name": true,
207
- }
181
+ {
182
+ "org.iso.18013.5.1.mDL": {
183
+ "org.iso.18013.5.1": {
184
+ "hair_colour": true,
185
+ "given_name_national_character": true,
186
+ "family_name_national_character": true,
187
+ "given_name": true,
208
188
  }
209
- }
210
-
211
- - resolve: The promise to be resolved
212
- - reject: The promise to be rejected
213
-
214
- */
189
+ }
190
+ }
191
+
192
+ - resolve: The promise to be resolved.
193
+ - reject: The promise to be rejected.
194
+ */
215
195
  @objc(generateResponse:withAcceptedFields:withResolver:withRejecter:)
216
196
  func generateResponse(
217
197
  documents: Array<Any>,
218
198
  acceptedFields: [AnyHashable: Any],
219
- _ resolve: @escaping RCTPromiseResolveBlock,
199
+ resolve: @escaping RCTPromiseResolveBlock,
220
200
  reject: @escaping RCTPromiseRejectBlock
221
201
  ){
222
202
  do {
@@ -238,9 +218,8 @@ class IoReactNativeIso18013: RCTEventEmitter {
238
218
 
239
219
  /**
240
220
  Sends a response containing the documents and the fields which the user decided to present generated by ``generateResponse``.
241
- It resolves to true after sending the response, otherwise it rejects if an error occurs while decoding the response.
242
221
  Currently there's not evidence of the verifier app responding to this request, thus we don't handle the response.
243
-
222
+ Resolves with a true boolean in case of success or rejects with an error code defined in ``ModuleErrorCodes``.
244
223
  - Parameters:
245
224
  - response: A base64 encoded string containing the response generated by ``generateResponse``
246
225
  - resolve: The promise to be resolved
@@ -249,7 +228,7 @@ class IoReactNativeIso18013: RCTEventEmitter {
249
228
  @objc(sendResponse:withResolver:withRejecter:)
250
229
  func sendResponse(
251
230
  response: String,
252
- _ resolve: @escaping RCTPromiseResolveBlock,
231
+ resolve: @escaping RCTPromiseResolveBlock,
253
232
  reject: @escaping RCTPromiseRejectBlock
254
233
  ){
255
234
  do{
@@ -265,24 +244,25 @@ class IoReactNativeIso18013: RCTEventEmitter {
265
244
 
266
245
  /**
267
246
  Sends an error response during the presentation according to the SessionData status codes defined in table 20 of the ISO18013-5 standard.
247
+ Resolves to true or rejects with an error code defined in ``ModuleErrorCodes``.
268
248
  - Parameters:
269
- - status: The status error to be sent is an integer of type ``SessionDataStatus``:
249
+ - code: The status error to be sent is an integer of type ``SessionDataStatus``:
270
250
  ```
271
251
  10 -> Error: session encryption
272
252
  11 -> Error: CBOR decoding
273
253
  20 -> Session termination
274
254
  ```
275
- - resolve: The promise to be resolved
276
- - reject: The promise to be rejected
255
+ - resolve: The promise to be resolved.
256
+ - reject: The promise to be rejected.
277
257
  */
278
258
  @objc(sendErrorResponse:withResolver:withRejecter:)
279
- func sendErrorResponse(status: UInt64, _ resolve: @escaping RCTPromiseResolveBlock,
280
- reject: @escaping RCTPromiseRejectBlock){
259
+ func sendErrorResponse(code: UInt64, _ resolve: @escaping RCTPromiseResolveBlock,
260
+ reject: @escaping RCTPromiseRejectBlock){
281
261
  do{
282
- if let statusEnum = SessionDataStatus(rawValue: status) {
262
+ if let statusEnum = SessionDataStatus(rawValue: code) {
283
263
  try Proximity.shared.errorPresentation(statusEnum)
284
264
  } else {
285
- reject(ModuleErrorCodes.sendErrorResponseError.rawValue, "Invalid status code provided: \(status)", nil)
265
+ reject(ModuleErrorCodes.sendErrorResponseError.rawValue, "Invalid status code provided: \(code)", nil)
286
266
  }
287
267
  resolve(true)
288
268
  }catch let error{
@@ -293,16 +273,14 @@ class IoReactNativeIso18013: RCTEventEmitter {
293
273
 
294
274
  /**
295
275
  Closes the bluetooth connection and clears any resource.
296
- It resolves to true after closing the connection.
297
-
276
+ Resolves to true after closing the connection or rejects with an error code defined in ``ModuleErrorCodes``.
298
277
  - Parameters:
299
- - resolve: The promise to be resolved
300
- - reject: The promise to be rejected
301
-
278
+ - resolve: The promise to be resolved.
279
+ - reject: The promise to be rejected.
302
280
  */
303
281
  @objc(close:withRejecter:)
304
282
  func close(
305
- _ resolve: @escaping RCTPromiseResolveBlock,
283
+ resolve: @escaping RCTPromiseResolveBlock,
306
284
  reject: @escaping RCTPromiseRejectBlock
307
285
  ) {
308
286
  Proximity.shared.stop()
@@ -310,13 +288,11 @@ class IoReactNativeIso18013: RCTEventEmitter {
310
288
  }
311
289
 
312
290
  /**
313
- Converts a device requested from the `onDocumentRequestReceived` callback into a serializable JSON.
314
-
315
- - Parameters:
316
- - request: The request returned from `onDocumentRequestReceived` which contains an array of tuples consists of a doctype, namespaces and the requested claims with a boolean value indicating wether or not the device which is making the request has an intent to retain the dataß
317
-
318
- - Returns: A JSON string representing the device request or nil if an error occurs
319
- */
291
+ Converts a device requested from the `onDocumentRequestReceived` callback into a serializable JSON.
292
+ - Parameters:
293
+ - request: The request returned from `onDocumentRequestReceived` which contains an array of tuples consists of a doctype, namespaces and the requested claims with a boolean value indicating wether or not the device which is making the request has an intent to retain the data.
294
+ - Returns: A JSON string representing the device request or nil if an error occurs.
295
+ */
320
296
  private func deviceRequestToJson(request: [(docType: String, nameSpaces: [String: [String: Bool]], isAuthenticated: Bool)]?) -> String? {
321
297
  var jsonRequest : [String: AnyHashable] = [:]
322
298
  request?.forEach({
@@ -394,13 +370,45 @@ class IoReactNativeIso18013: RCTEventEmitter {
394
370
  }
395
371
  }
396
372
 
397
- @objc func generateOID4VPDeviceResponse(
398
- _ clientId: String,
373
+ /**
374
+ Generates a CBOR encoded device response for ISO 18013-7 mDL remote presentation using OID4VP.
375
+ Resolves with the base64 encoded device response or rejects with an error code defined in ``ModuleErrorCodes``.
376
+ - Parameters:
377
+ - clientId: The client id extracted from OID4VP session.
378
+ - responseUri: The response URI extracted from OID4VP session.
379
+ - authorizationRequestNonce - The authorization request nonce extracted from OID4VP session.
380
+ - mdocGeneratedNonce - the mdoc generated nonce to be generated.
381
+ - documents: An array containing documents. Each document is defined as a map containing:
382
+ - issuerSignedContent which is a base64 or base64url encoded string representing the credential;
383
+ - alias which is the alias of the key used to sign the credential;
384
+ - docType which is the document type.
385
+ - acceptedFields: A dictionary of elements, where each element must adhere to the structure of AcceptedFieldsDict—specifically, a `[String: [String: [String: Bool]]]`. The outermost key represents the credential doctype. The inner dictionary contains namespaces, and for each namespace, there is another dictionary mapping requested claims to a boolean value, which indicates whether the user is willing to present the corresponding claim. Example:
386
+
387
+
388
+ {
389
+ "org.iso.18013.5.1.mDL": {
390
+ "org.iso.18013.5.1": {
391
+ "hair_colour": true,
392
+ "given_name_national_character": true,
393
+ "family_name_national_character": true,
394
+ "given_name": true,
395
+ },
396
+ {...}
397
+ },
398
+ {...}
399
+ }
400
+
401
+ - resolve: The promise to be resolved.
402
+ - reject: The promise to be rejected.
403
+ */
404
+ @objc(generateOID4VPDeviceResponse:withResponseUri:withAuthorizationRequestNonce:withMdocGeneratedNonce:withDocuments:withAcceptedFields:withResolver:withRejecter:)
405
+ func generateOID4VPDeviceResponse(
406
+ clientId: String,
399
407
  responseUri: String,
400
408
  authorizationRequestNonce: String,
401
409
  mdocGeneratedNonce: String,
402
410
  documents: [Any],
403
- fieldRequestedAndAccepted: String,
411
+ acceptedFields: [AnyHashable: Any],
404
412
  resolver resolve: RCTPromiseResolveBlock,
405
413
  rejecter reject: RCTPromiseRejectBlock
406
414
  ) {
@@ -414,7 +422,7 @@ class IoReactNativeIso18013: RCTEventEmitter {
414
422
  )
415
423
 
416
424
  let documentsAsProximityDocument = try parseDocuments(documents: documents)
417
- let items = try JSONDecoder().decode([String : [String : [String : Bool]]].self, from: Data(fieldRequestedAndAccepted.utf8))
425
+ let items = try parseAcceptedFields(acceptedFields: acceptedFields)
418
426
  let response = try Proximity.shared.generateDeviceResponse(items: items, documents: documentsAsProximityDocument, sessionTranscript: sessionTranscript)
419
427
  resolve(Data(response).base64EncodedString())
420
428
  } catch let parsingError as ParsingError{
@@ -1,92 +1,40 @@
1
- ## CBOR
1
+ # CBOR
2
2
 
3
3
  This module provides methods to decode CBOR data into readable objects.
4
4
 
5
5
  ```typescript
6
- import { CBOR } from '@pagopa/io-react-native-cbor';
6
+ import { CBOR } from '@pagopa/io-react-native-iso18013';
7
7
  ```
8
8
 
9
- ### Methods
9
+ ## Methods
10
10
 
11
11
  #### `decode`
12
12
 
13
- This method allows to decode CBOR data into readable JSON objects.
14
- Returns a `Promise` which resolves to a JSON object, or rejects with an instance of `CborFailure` in case of failure.
13
+ Decodes CBOR data into readable JSON objects.
15
14
 
16
15
  **Note**: this method does not decode nested CBOR objects and therefore complex objects needs additional manual decoding
17
16
 
18
17
  ```typescript
19
- try {
20
- const decoded = await CBOR.decode('...');
21
- } catch (e) {
22
- const { message, userInfo } = e as CborFailure;
23
- }
18
+ const decoded = await CBOR.decode('...');
24
19
  ```
25
20
 
26
21
  #### `decodeDocuments`
27
22
 
28
- This metod allows the decoding of CBOR data which contains MDOC objects.
29
- Returns a promise wich resolves to a [Documents](#documents) object, or rejects with an instance of `CborFailure` in case of failure.
30
-
31
- ```typescript
32
- try {
33
- const decoded = await CBOR.decodeDocuments('...');
34
- } catch (e) {
35
- const { message, userInfo } = e as CborFailure;
36
- }
37
- ```
38
-
39
- ### Types
40
-
41
- #### `Documents`
42
-
43
- ```typescript
44
- type Documents = {
45
- status?: number;
46
- version?: string;
47
- documents?: Array<MDOC>;
48
- };
49
- ```
50
-
51
- #### `MDOC`
23
+ Decodes CBOR data containing MDOC objects.
52
24
 
53
25
  ```typescript
54
- type MDOC = {
55
- docType?: DocumentType;
56
- issuerSigned?: IssuerSigned;
57
- };
26
+ const decoded = await CBOR.decodeDocuments('...');
58
27
  ```
59
28
 
60
- #### `IssuerSigned`
61
-
62
- ```typescript
63
- type IssuerSigned = {
64
- nameSpaces?: Record<string, Array<DocumentValue>>;
65
- issuerAuth?: string;
66
- };
67
- ```
29
+ #### `decodeIssuerSigned`
68
30
 
69
- #### `DocumentValue`
31
+ Decodes CBOR data containing an Issuer Signed object.
70
32
 
71
33
  ```typescript
72
- type DocumentValue = {
73
- digestID?: number;
74
- random?: string;
75
- elementIdentifier?: string;
76
- elementValue?: string;
77
- };
78
- ```
79
-
80
- #### `DocumentType`
81
-
82
- ```typescript
83
- enum DocumentTypeEnum {
84
- MDL = 'org.iso.18013.5.1.mDL',
85
- EU_PID = 'eu.europa.ec.eudi.pid.1',
86
- }
34
+ const decoded = await CBOR.decodeIssuerSigned('...');
87
35
  ```
88
36
 
89
- ### Error Codes
37
+ ## Errors
90
38
 
91
39
  This table contains the list of error codes that can be thrown by the `CBOR` module which are mapped via the `ModuleErrorCodes` type:
92
40
  | Type | Platform | Description |