@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.
- package/README.md +10 -5
- package/android/build.gradle +7 -1
- package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeCborModule.kt +90 -58
- package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeIso18013Module.kt +216 -100
- package/android/src/test/java/com/ioreactnativeiso18013/Base64UtilsTest.kt +66 -0
- package/android/src/test/java/com/ioreactnativeiso18013/IoReactNativeIso18013Test.kt +508 -0
- package/ios/IoReactNativeCbor.mm +21 -21
- package/ios/IoReactNativeCbor.swift +70 -22
- package/ios/IoReactNativeIso18013.mm +10 -10
- package/ios/IoReactNativeIso18013.swift +89 -81
- package/lib/module/cbor/cbor/README.md +11 -63
- package/lib/module/cbor/cbor/decoder.js +13 -23
- package/lib/module/cbor/cbor/decoder.js.map +1 -1
- package/lib/module/cbor/cose/README.md +1 -1
- package/lib/module/cbor/cose/sign.js +4 -3
- package/lib/module/cbor/cose/sign.js.map +1 -1
- package/lib/module/iso18013/iso18013-5/README.md +66 -26
- package/lib/module/iso18013/iso18013-5/index.js.map +1 -1
- package/lib/module/iso18013/iso18013-5/proximity.js +19 -6
- package/lib/module/iso18013/iso18013-5/proximity.js.map +1 -1
- package/lib/module/iso18013/iso18013-5/request.js +0 -17
- package/lib/module/iso18013/iso18013-5/request.js.map +1 -1
- package/lib/module/iso18013/iso18013-7/README.md +32 -36
- package/lib/module/iso18013/iso18013-7/remote.js +11 -12
- package/lib/module/iso18013/iso18013-7/remote.js.map +1 -1
- package/lib/typescript/src/cbor/cbor/decoder.d.ts +12 -22
- package/lib/typescript/src/cbor/cbor/decoder.d.ts.map +1 -1
- package/lib/typescript/src/cbor/cose/sign.d.ts +4 -3
- package/lib/typescript/src/cbor/cose/sign.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/iso18013-5/index.d.ts +2 -2
- package/lib/typescript/src/iso18013/iso18013-5/index.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts +20 -8
- package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/iso18013-5/request.d.ts +0 -23
- package/lib/typescript/src/iso18013/iso18013-5/request.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/iso18013-7/index.d.ts +1 -1
- package/lib/typescript/src/iso18013/iso18013-7/index.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts +11 -11
- package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts.map +1 -1
- package/lib/typescript/src/iso18013/types.d.ts +25 -0
- package/lib/typescript/src/iso18013/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cbor/cbor/README.md +11 -63
- package/src/cbor/cbor/decoder.ts +13 -23
- package/src/cbor/cose/README.md +1 -1
- package/src/cbor/cose/sign.ts +5 -4
- package/src/iso18013/iso18013-5/README.md +66 -26
- package/src/iso18013/iso18013-5/index.ts +2 -6
- package/src/iso18013/iso18013-5/proximity.ts +20 -8
- package/src/iso18013/iso18013-5/request.ts +0 -22
- package/src/iso18013/iso18013-7/README.md +32 -36
- package/src/iso18013/iso18013-7/index.ts +1 -1
- package/src/iso18013/iso18013-7/remote.ts +12 -14
- 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
|
-
|
|
9
|
-
|
|
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
|
|
15
|
-
guard let json = CborCose.jsonFromCBOR(data:
|
|
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
|
-
|
|
28
|
-
|
|
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
|
|
34
|
-
guard let json = CborCose.decodeCBOR(data:
|
|
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
|
-
|
|
46
|
-
|
|
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
|
|
52
|
-
guard let json = CborCose.issuerSignedCborToJson(data:
|
|
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
|
-
|
|
64
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
99
|
-
let publicKeyJson = try JSONSerialization.data(withJSONObject:
|
|
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:
|
|
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)
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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(
|
|
280
|
-
|
|
259
|
+
func sendErrorResponse(code: UInt64, _ resolve: @escaping RCTPromiseResolveBlock,
|
|
260
|
+
reject: @escaping RCTPromiseRejectBlock){
|
|
281
261
|
do{
|
|
282
|
-
if let statusEnum = SessionDataStatus(rawValue:
|
|
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: \(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
398
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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-
|
|
6
|
+
import { CBOR } from '@pagopa/io-react-native-iso18013';
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Methods
|
|
10
10
|
|
|
11
11
|
#### `decode`
|
|
12
12
|
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
docType?: DocumentType;
|
|
56
|
-
issuerSigned?: IssuerSigned;
|
|
57
|
-
};
|
|
26
|
+
const decoded = await CBOR.decodeDocuments('...');
|
|
58
27
|
```
|
|
59
28
|
|
|
60
|
-
#### `
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
type IssuerSigned = {
|
|
64
|
-
nameSpaces?: Record<string, Array<DocumentValue>>;
|
|
65
|
-
issuerAuth?: string;
|
|
66
|
-
};
|
|
67
|
-
```
|
|
29
|
+
#### `decodeIssuerSigned`
|
|
68
30
|
|
|
69
|
-
|
|
31
|
+
Decodes CBOR data containing an Issuer Signed object.
|
|
70
32
|
|
|
71
33
|
```typescript
|
|
72
|
-
|
|
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
|
-
|
|
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 |
|