Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This section offers an overview of the architecture and technologies utilized within Inji Wallet, ensuring compatibility, security, and efficiency in the management of Verifiable Credentials.
This section intends to provide an overview of the technologies, tools and frameworks utilized to build Inji Wallet:
Tool / Technology | Version | Description | License |
---|---|---|---|
This section intends to provide an overview of the technologies, tools and frameworks utilized to build native libraries:
Tool / Technology | Version | Description | License |
---|---|---|---|
Face Match is an optional component in Inji Wallet. This is built as a standard that allows anyone to integrate their Facematch SDK. Its expected that the wallet providers would integrate the SDK that matches the specification.
The current specification is in draft state.
We extend our sincere appreciation to the IRIScan team for their invaluable support to MOSIP by providing an opensource face match SDK for our internal reference integration. We are truly impressed by your commitment and outstanding contribution. We welcome and invite our other esteemed partners to collaborate with MOSIP, for a similar integration.
To install any face sdk module, please add it's dependency in the package.json
file.
Once done rebuild the Inji Wallet.
The Inji Wallet should be able to integrate and use the face sdk.
This feature enables Inji Wallet to verify specific parameters for liveness. We utilize local face verification to guarantee the user's presence during a transaction. This measure is implemented to combat fraud, going beyond the ISO/IEC 30101 standard.
The following guidelines apply to individuals who are developing the face SDK:
It is prohibited to collect any personally identifiable information (PII) or phone details.
Inji Wallet includes built-in telemetry, and all telemetry data must be transmitted to the designated system. Telemetry enhances Inji Wallet's observability features by capturing specific events, creating measures, and monitoring various user actions and events.
Recording or transmitting IP addresses, user details, Phone IMEI, phone numbers, or user photos in telemetry or logs is strictly prohibited.
The use of phone numbers and device fingerprints should be limited to managing the SDK license.
Secure Keystore is a library exclusively for Android platform. The devices which have a can use this library to perform encryption, decryption and computation of HMAC on the native side using the Hardware backed security features.
Maven Snapshots are available
NPM modules are available
The Secure Keystore is an independent module published as NPM module which provides Android APIs for the same on React. On a React Native application, this can be installed via
For RSA based Key Pair
For symmetric key
deviceSupportsHardware: boolean
Checks if the device supports hardware keystore.
generateKey(alias: string) => void
Generates a symmetric key for encryption and decryption.
generateKey(alias: string) => string
Generates an asymmetric RSA key Pair for signing.
encryptData(alias: string, data: string) => string
Encrypts the given data using the key that is assigned to the alias. Returns back encrypted data as a string.
decryptData(alias: string, encryptionText: string) => string
Decrypts the given encryptionText
using the key that is assigned to the alias. Returns back the data as a string.
sign(alias: string, data: string) => string
Creates a signature for the given data using the key that is assigned to the alias. Returns back the signature as a string.
hasAlias(alias: string) => boolean
Checks if the given alias is present in the keystore.
This is the module that supports transferring verifiable credentials (VC) over Bluetooth Low Energy (BLE).
Let's have a look at how BLE communication works in general between the two devices A & B.
presents the kotlin library for tuvali
to get details on swift artifact.
contains the artefacts in maven.
In build.gradle.kts add the following:
The kotlin library has been added to your project.
Download swift artifact (ios-tuvali-library) from the repository.
Open your project in XCode.
Goto File > Add Package Dependencies.
Select Add Local option.
Add the artifact folder.
The swift library has been added to your project.
Before we understand how Tuvali works, let's go through BLE communication.
In BLE communication, one device is designated as Peripheral and another one designated as Central.
Peripheral can perform advertisement which can be read by a Central device and connected to it, if the advertisement is connectable.
Once the connection is made, Central can perform further actions on the device like
discovering services and characteristics
subscribing to notifications on characteristics
write/ read data from characteristics
disconnect from device
While peripheral can perform actions like
sending notifications to subscribed characteristics
respond to read requests from Central
The above diagram explains the sequence of actions for BLE communication in general.
Advertisement from Peripheral
Connection establishment & additional data exchange
Service & Characteristic discovery from Central
The characteristic subscription on Peripheral
Write with response to characteristic
Write without response to the characteristic
Send Notification from GATT Server
Disconnection from GATT Server/ Client
More details about other BLE terminology used here can be found in standard BLE specifications of 4.2 and above.
Note: Tuvali is supposed to implement OpenID for VP over BLE specification. As part of it, both VP request and response transfer should be implemented. However the current version of Tuvali only transfers VC from Central to Peripheral.
In the case of Tuvali, the entire VC transfer flow can be divided into the following stages
Connection Setup & Cryptographic key exchange
Data transfer
Connection Closure
Steps 1 to 6 mentioned in the above diagram explain how the first stage is achieved. Before even the advertisement is started, the peripheral generates a 32-byte public key. This public key is sent to Central in two parts. The first part will have 5 bytes of the public key sent as part of the advertisement payload and while the second part is sent as part of SCAN_RESP.
Since the advertisement from Peripheral is of connectable type, Central would send out a SCAN_REQ on receiving the advertisement and gets the remaining 27 bytes of the peripheral public key. Post that, Central would derive a public key pair and send its 32 bytes public key on Identify characteristic of Peripheral.
Once the public keys are exchanged between Central and Peripheral, a set of keys are derived on both sides which would be used for encryption and decryption of data on the wire.
Cryptographic Algorithm usage:
Ephemeral Key Pair is generated from X25519 curve
Key Agreement uses ECKA-DH (Elliptic Curve Key Agreement Algorithm – Diffie-Hellman) as defined in BSI TR-03111
Wallet and Verifier derives respective keys using HKDF as defined in RFC5869
Encryption/Decryption uses AES-256-GCM (192) (GCM: Galois Counter Mode) as defined in NIST SP 800-38D
Steps 7 to 11 mentioned in the above diagram explain how the second stage is achieved. Before VC is transferred, Central performs encryption and compression and communicates the resultant data size by writing to Response Size characteristic to Peripheral. The actual data transfer would happen on Submit Response
characteristic.
Since the maximum allowed write value for a characteristic is limited to 512 bytes. The actual VC data is split by a component called Chunker into multiple smaller chunks. After the split, the data is transferred on the Submit response
characteristics one after another until all chunks are completely sent.
Peripheral on the other hand, receives data on the Submit response
characteristic. The received chunks are collected and the final VC is assembled by a component called Assembler.
At the end of sending one frame of data from Central. It would request a transfer report via Transfer report request
characteristic. Peripheral response with a summary of missing/corrupted chunks sequence numbers via another Transfer report summary
characteristic.
Central would read the Transfer report summary to understand if the Peripheral received all the chunks properly. If the summary report has at least one chunk sequence number. Central would send those specific chunks to the Peripheral which is called the Failure frame.
The failure frame will be sent from Central repeatedly until the Transfer report summary is successful. If during the process, Central reached the maximum allowed failure frame retry limit, the transfer is halted, devices will be disconnected and an error is generated (Please refer to API documentation on how this error can be read).
Gzip is the Compression algorithm used with default compression level
Each chunk have 2 bytes of CRC-16/Kermit added. Parameters for the same are: width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 residue=0x0000 name="CRC-16/KERMIT"
On a successful data transfer
On non-recoverable error occurred on Peripheral
Peripheral notify Central to perform disconnection via Disconnect
characteristic mentioned in Step 12 of the above diagram.
Central also performs disconnect in the following scenarios:
On a successful data transfer
Non-recoverable error on Central
Peripheral is out of range/ disconnected
Destroy Connection API
As part of connection closure, both central and peripheral clean the held resources, cryptographic keys, and Bluetooth resources, to ensure that the subsequent transfer happens smoothly.
Note: All the cryptographic keys generated/ derived are used only for a single VC transfer session. The library strictly ensures they are not re-used in subsequent VC transfers post connection closure.
Error Code Format: <Component(2 Character)Role(1 Character)>-<Stage(3 Character)>-<Number(3 Character)>
Current Supported Stages: CON(Connection) | KEX(Key Exchange) | ENC(Encryption) | TRA(Transfer) | REP(Report) | DEC(Decryption) | UNK (Stage is unknown) Current Component+ Role Combinations: TVW(Tuvali+Wallet) | TVV(Tuvali+Verifier) | TUV(Tuvali where role is unknown)
List of Supported Error Codes:
UnknownException: TUV_UNK_001
WalletUnknownException: TVW_UNK_001
CentralStateHandlerException: TVW_UNK_002
WalletTransferHandlerException: TVW_UNK_003
VerifierUnknownException: TVV_UNK_001
PeripheralStateHandlerException: TVV_UNK_002
VerifierTransferHandlerException: TVV_UNK_003
InvalidURIException: TVW_CON_001
MTUNegotiationException: TVW_CON_002
ServiceNotFoundException: TVW_CON_003
TransferFailedException: TVW_REP_001
UnsupportedMTUSizeException: TVV_CON_001
CorruptedChunkReceivedException: TVV_TRA_001
TooManyFailureChunksException: TVV_TRA_002
Failed to transfer
message and wallet receive a Disconnected
message on the screen.Possible error scenarios:
During VC transfer, if there is a failure in the transfer of more than 70% of the data we get an exception on the verifier side and it disconnects from the wallet.
After the verifier and wallet establish a connection, the wallet initiates an MTU negotiation with the verifier. If the negotiated MTU is less than 64 Bytes, then the verifier throws an exception and disconnects from the wallet.
If the verifier receives the size of the VC as 0, it raises an exception and disconnects from the wallet.
Failed to transfer
message and the verifier receives a Disconnected
message on the screen.Possible error scenarios:
After the verifier and wallet establish a connection, the wallet initiates an MTU negotiation with the verifier. If the wallet is unable to negotiate the MTU with the verifier, it raises an exception and disconnects from the verifier.
During VC transfer, if the transfer cannot be completed within the specified limit of retries, the wallet raises an exception and disconnects from the verifier.
After the wallet sends all the chunks, it requests a transfer report. If the wallet is not able to send the request, it raises an exception and disconnects from the verifier.
Below are the exception message and the disconnect message which appears on the screen during the error.
This message is displayed on the device throwing the exception.
This message is displayed whenever a device gets disconnected.
Backoff Strategy: Exponential Backoff is a technique that retries a failing operation, with an exponentially increasing wait time, up to a maximum retry count(MAX_RETRY_LIMIT) or maximum backoff time(MAX_ELAPSE_TIME).
Initially, it starts with 2 ms as wait time (INITIAL_WAIT_TIME) and increases exponentially with each failure until the count reaches MAX_EXPONENT after which the wait time becomes constant (INITIAL_WAIT_TIME ^ MAX_EXPONENT).
BLE Service Discovery: After the connection is established, the central attempts to discover all the services hosted by the peripheral. If it fails to discover our service, then the exponential backoff-based retry will kick in. Here are the values:
MAX_RETRY_LIMIT is 5 for Android and 10 for IOS
MAX_ELAPSE_TIME is 100 ms
MAX_EXPONENT is 5
Request Transfer Report [only for iOS]: After the wallet writes all the chunks to the verifier, it requests the transfer report. If the transfer report request write fails, then the exponential backoff-based retry will kick in. Here are the values:
MAX_RETRY_LIMIT is 5
MAX_ELAPSE_TIME is 100 ms
MAX_EXPONENT is 5
Dynamic MTU negotiation:
Android: After the connection is established, the wallet initiates an MTU negotiation with an initial value of 512 bytes. If it fails, it retries with 185 and 100 bytes subsequently with a wait time of 500 ms each. If the negotiation fails after all retries, it throws an exception and disconnects from the wallet.
iOS: iOS kicks off an MTU exchange automatically upon connection
MAX_ALLOWED_DATA_LEN (509 Bytes): Maximum data length allowed for one write for both wallet and verifier.
MIN_MTU_REQUIRED (64 Bytes): Minimum number of bytes required to share public key transfer of the wallet is 46. In order not to operate in edges, we chose the nearest value in the power of 2 i.e., 64.
MAX_FAILURE_FRAME_RETRY_LIMIT (15): Maximum limit to retry sending failure chunks to the verifier.
IDENTIFY_REQUEST_CHAR_UUID (00000006-5026-444A-9E0E-D6F2450F3A77): Characteristic for sending the public key of the wallet.
REQUEST_SIZE_CHAR_UUID (00000004-5026-444A-9E0E-D6F2450F3A77): Characteristic for requesting VC size by wallet from verifier.
REQUEST_CHAR_UUID (00000005-5026-444A-9E0E-D6F2450F3A77): Characteristic for requesting the VC by the verifier.
RESPONSE_SIZE_CHAR_UUID (00000007-5026-444A-9E0E-D6F2450F3A77): Characteristic for sending VC size to the verifier.
SUBMIT_RESPONSE_CHAR_UUID (00000008-5026-444A-9E0E-D6F2450F3A77): Characteristic for sending the entire VC.
TRANSFER_REPORT_REQUEST_CHAR_UUID (00000009-5026-444A-9E0E-D6F2450F3A77): Characteristic for requesting for transfer report from the verifier.
TRANSFER_REPORT_RESPONSE_CHAR_UUID (0000000A-5026-444A-9E0E-D6F2450F3A77): Characteristic for sending transfer report to the wallet
VERIFICATION_STATUS_CHAR_UUID (00002037-0000-1000-8000-00805f9b34fb): Characteristic for informing the wallet if the VC is accepted or rejected.
DISCONNECT_CHAR_UUID (0000000B-5026-444A-9E0E-D6F2450F3A77): Characteristic for notifying the wallet to initiate the disconnection between the devices.
SERVICE_UUID (00000001-0000-1000-8000-00805f9b34fb): Service UUID of the verifier
SCAN_RESPONSE_SERVICE_UUID (00000002-0000-1000-8000-00805f9b34fb): Service UUID for uniquely identifying the scan response data to the wallet's SCAN_REQ
Below are the guidelines and specifications for integrating any software development kit (SDK) with Inji Wallet:
The SDK should be implemented as a npm module that supports the React Native framework.
For example, the npm modules, and , demonstrate suitable implementations.
The SDK should provide simple APIs for integration purposes.
These APIs should include an API for instantiation or initialization, such as the init or constructor API.
The SDK should also include additional APIs that perform the necessary actions.
There should be an API available to disconnect the SDK, if needed.
If possible, it would be beneficial for these APIs to be asynchronous. This enables users to continue using the application without experiencing any UI blocking.
To enhance logging and traceability, the API may accept an optional parameter known as traceabilityId
.
By adhering to these specifications, the integrated SDK will enhance the functionality and usability of the application.
This section contains various guides and information that could benefit the developers, system integrators, relying parties and end users.
For more information on how to get started with integrations, read through:
Tuvali - Sharing via BLE
Face Match
Secure Keystore
BLE Verifier
PixelPass
Telemetry (details coming up soon)
Inji Wallet utilizes multiple libraries to provide a seamless experience.
These libraries are accessible as NPM modules, allowing seamless integration with other mobile wallets.
The libraries are as follows:
Tuvali - Sharing via BLE
Face Match
Secure Keystore
BLE Verifier
PixelPass
VCI-client
Telemetry (coming soon)
The transfer of downloaded Verifiable Credential from the Wallet to Verifier is facilitated by a React Native library named Tuvali.
Tuvali is actively developed and maintained by MOSIP.
It does not support iOS for initiating the BLE exchanges, hence preventing two iOS devices from transferring VC.
Note:
This SDK internally employs a tflite
model, which must be created by the integrating party. The model, trained using resident faces, is stored on the MOSIP file server. Inji Wallet currently utilizes the face matcher SDK (soon to be replaced by the NPM module) for offline face authentication.
The SDK is employed in two scenarios:
During Offline VC Sharing: Residents can perform selfie authentication before sharing the VC with the relying party. The app opens the camera, allowing residents to take a selfie, which is then validated against the VC image to verify the resident's presence. During Online Login: Residents can scan the QR code from the relying party portal and opt to log in using Inji Wallet for services. In this process, residents undergo selfie authentication against the VC to confirm their presence.
It also helps to sign with aliases, created as part of key pair generation.
As the description says, this module is only for Android devices which support hardware keystore.
This library is available as Kotlin artefact in maven as well as npm module for react native application. Inji Wallet is integrated with the kotlin artefact of secure-keystore.
In order to reduce the key size during credential download request, Inji Wallet is using RSA-2048 instead of RSA-4096 bits keys.
Note:
This feature is exclusive to the Android operating system.
It is only compatible with devices that have a hardware keystore.
Note:
The PixelPass library offers a powerful solution for creating and decoding QR codes for Verifiable Credentials (VCs). It is designed to optimize the size of the data encoded within a QR code, making it easier to store and share credential information. The library achieves this by utilizing advanced compression and encoding techniques, ensuring smaller QR codes that maintain the integrity and security of the data.
PixelPass uses zlib compression with a level 9 setting, which significantly reduces the data size before encoding. It then applies base45 encoding to further compress the data into a QR code-friendly format. Additionally, the library can decode any QR code data previously encoded using its own compression and encoding algorithms, ensuring seamless interoperability.
Note:
VCI-Client library carries out the credential request from the consumer application (mobile wallet or web) and redirects the issuance/issuer. The library creates a request with the credential format, jwtproof of the wallet, issuer meta data and the access token received for authorization and provides VC as the response back to the consumer application for storage.
Note:
Note: The publication of this project is currently a work in progress and has not been released yet. Stay tuned for further announcements!
enables offline VC transfer between mobile devices via Bluetooth Low Energy (BLE). The below table represents the supported roles for Android and iOS devices.
Wallet | Verifier | VC transfer support |
---|
To learn more about Tuvali's implementation, refer .
For information on Tuvali's permissions and requirements, refer .
To understand Tuvali and Inji Wallet integration, along with API documentation, refer.
To check the NPM module, click .
Maven snapshots are available
The face matcher SDK internally implements native functionalities for Android and iOS, utilizing and to identify faces.
Upon the initial launch of Inji Wallet, the model is downloaded in the background and stored in the cache. Refer to check the API specifications for the face matcher model.
The library is designed for the purpose of creating and storing key-pairs in the hardware keystore of Android devices. The library also supports encryption, decryption, and HMAC calculation functionalities.
To check all the APIs supported by this module, refer .
To understand about the library and the API documentation, refer .
To check the NPM module, click .
Maven snapshots are available
The is the module built for verifiers for receiving VC via BLE. This is a wrapper built on Tuvali with simplified APIs.
To know more about API and how to integrate, refer .
To check the NPM module, click .
Additionally, for a JSON data, the library employs CBOR encoding and decoding to minimize the size even further. When a JSON Mapper similar to is provided, PixelPass maps the data, applies CBOR encoding/decoding, and compresses the data, achieving maximum size reduction. Developed and maintained by MOSIP, PixelPass is continually updated to provide reliable and efficient QR code generation and decoding capabilities.
Refer to the PixelPass repository .
To understand about the installation and the API documentation, refer .
For a hands-on experience of Generate a VC, Generate QR Code for the VC and Verify the same using Inji Verify, please click .
To check the NPM module, click.
Maven snapshots are available
Refer to the VCI-Client repository .
To understand about the installation and the API documentation, refer .
To check the NPM module, click .
Maven snapshots are available
The module is derived from the module. It is responsible for generating events that can provide valuable analytics.
To know more about each of these, refer .
0.71.8
It brings the best parts of developing with React to native development. It's a best-in-class JavaScript library for building user interfaces.
4.9.5
A strongly typed programming language that builds on JavaScript and uses type inference to give great tooling without additional code.
29.5.11
Jest is a well-known JavaScript testing framework and is extensively used to test React applications
minSDK 24 compileSDK 24 targetSDK 34
Android is a mobile operating system based on a modified version of the Linux kernel and other open-source software, designed primarily for touchscreen mobile devices. This is used to build the application for running on Android devices
13.4
iOS is a mobile operating system developed by Apple exclusively for its smartphones. Swift is a high-level general-purpose, multi-paradigm, compiled programming language created to develop on iOS.
2.0.0 Java 17
Kotlin is a modern statically typed programming language
minSDK 23 compileSDK 33
Android is a mobile operating system based on a modified version of the Linux kernel and other open-source software, designed primarily for touchscreen mobile devices. This is used to build the application for running on Android devices
13.4
iOS is a mobile operating system developed by Apple exclusively for its smartphones. Swift is a high-level general-purpose, multi-paradigm, compiled programming language created to develop on iOS.
Android | Android | Yes |
iOS | Android | Yes |
Android | iOS | No |
iOS | iOS | No |
Following permissions are required to be included in the AndroidManifest.xml
to access Bluetooth Low Energy on Android.
Permissions required for Central (Wallet) when target is Android 12 or higher
Permissions required for Central (Wallet) when target is Android 11 or lower
Permissions required for Peripheral (Verifier) when target is Android 12 or higher
Permissions required for Peripheral (Verifier) when target is Android 11 or lower
Following permissions are required to be included in info.plist
to access the Core Bluetooth APIs on iOS.
BLE version: BLE 4.2 and above.
Android version: Android version 9 (API level 28) and above.
iOS version: The SDK requires iOS minimum deployment target version as 13.0.
Wallet: In this role, Tuvali can discover Verifier devices over BLE and can connect and share data. This role is supported on both, Android and iOS devices meeting minimum version requirement.
Verifier: In this role, Tuvali can advertise itself to Wallets and receive data. This role is supported only on Android devices at the moment. iOS doesn't support being a Verifier.
This telemetry module is derived from the sunbird telemetry module. It is responsible for generating events that can provide valuable analytics.
Note: The publication of this project is currently a work in progress and has not been released yet. Stay tuned for further announcements.
Tuvali module is based on the OpenID for Verifiable Presentations over BLE implementation to support sending vc/vp using Bluetooth Low Energy local channel. The below sections explains the APIs of the library in detail.
Firstly, for establishing the secured connection over BLE the connection params which include name
and key
needs to be exchanged between the two devices. This exchange of parameters can be accomplished but is not limited to by using a QR code.
For example, use a QR code generator to visually display params and a QR code scanner to get params. A mobile app that displays a QR code can act as an Verifier
by including its connection params as data in the QR code and another device can act as Wallet
which scans the QR code, it can extract the connection parameters and initiate a BLE connection with the advertising device.
The Verifier device generates a URI using the startAdvertisement()
method and displays it as a QR code. Once the advertisement starts, the Verifier continuously advertises with a payload derived from the URI.
URI structure can be found in the spec. Currently the library doesnot support iOS as a verifier.But it can act as a wallet for android verifier.
The device that scans the QR code will extract the connection parameters from the QR code and set its connection parameters using the startConnection()
method :
The connection param is a URI with a name & a key. The name
is the client's name & the key
is the verfier's public key.
The key
part of the data is the same data that will be advertised by the verifier
device but in hex-encoded form.
E.g: OVPMOSIP://connect:?name=<>&key=<verifier public key>
Once the connection is established, wallet app can send the data in a secured way to the Verifier. Note: At this moment, we currently support data transfer from Wallet to Verifier only.
and verifier app can acknowledge it.
The following sequence of actions should be performed to transfer data over BLE:
Verifier must start advertising by calling verifier.startAdvertisement(name)
method
Subscribe to events using wallet.handleDataEvents
Initiate the secure connection using wallet.startConnection(uri)
. The Wallet public keys are exchanged with verifier on successful connection.
Wallet calls wallet.sendData(payload)
to transfer requisite data over BLE.
Send VC response - Verifier can exchange "Accept/Reject" status to Wallet with the following message type for verifier.sendVerificationStatus
method
Data received from other apps via BLE can be subscribed to using: Tuvali sends multiple events to propagate connection status, received data etc. These events can be subscribed to by calling:
on Wallet:
on Verifier:
Here are the different types of events that can be received
Events which are emitted by both Wallet and Verifier
ConnectedEvent
on BLE connection getting established between Wallet and Verifier
SecureChannelEstablishedEvent
on completion of key exchange between Wallet and Verifier
ErrorEvent
on any error in Wallet or Verifier
DisconnectedEvent
on BLE disconnection between Wallet and Verifier
DataSentEvent
on completion of Data transfer from the Wallet Side
VerificationStatusReceivedEvent
on received verification status from Verifier
DataReceivedEvent
on receiving data from the Wallet Side
The device on which app is running can destroy the connection by calling disconnect() method:
The below diagram explains the series of handshakes between the Verifier and the Wallet device.
PixelPass is a versatile and easy-to-use library designed to simplify working with QR codes and data compression. It allows you to generate QR codes from any given data with just a single function. If you’re working with JSON, PixelPass can take that data, compress it, and convert it into a compact format using CBOR encoding, making it smaller and more efficient for QR code generation. The library can also decode this compressed data, turning CBOR back into the original JSON format. Additionally, for more complex use cases, PixelPass offers the ability to map your JSON data to a specific structure, compress it, and encode it into CBOR. Later, you can also reverse this process, decoding the CBOR back into its mapped JSON structure. With these capabilities, PixelPass makes managing, compressing, and encoding data for QR codes easy and efficient.
PixelPass has NPM, Kotlin, Swift and Java artifacts available.
Compresses data using zlib with the highest compression level (level 9).
Encodes and decodes data with the base45 format.
For JSON data, applies CBOR encoding/decoding to achieve additional size reduction.
With JSON and a Mapper provided, maps the JSON and then performs CBOR encoding/decoding to further shrink the data size.
As a node project:
npm i @mosip/pixelpass
As a Kotlin/Java dependency:
Gradle
implementation("io.mosip:pixelpass:0.5.0")
Maven
To include PixelPass in your Swift project, follow the below steps:
Clone the PixelPass library locally.
Create a new Swift project.
Add package dependency: PixelPass
Below are the APIs provided by the PixelPass library:
generateQRCode( data, ecc , header )
The generateQRCode
takes a data, ECC (Error correction level) which when not passed defaults to L and header which defaults to empty string if not passed. Returns a base64 encoded PNG image.
data
- Data needs to be compressed and encoded.
ecc
- Error Correction Level for the QR generated. defaults to "L"
.
header
- Data header need to be prepend to identify the encoded data. defaults to ""
.
generateQRData( data, header )
The generateQRData
takes a valid JSON string and a header which when not passed defaults to an empty string. This API will return a base45 encoded string which is Compressed > CBOR Encoded > Base45 Encoded
.
data
- Data needs to be compressed and encoded.
header
- Data header need to be prepend to identify the encoded data. defaults to ""
.
decode( data )
The decode
will take a string
as parameter and gives us decoded JSON string which is Base45 Decoded > CBOR Decoded > Decompressed
.
data
- Data needs to be decoded and decompressed without header.
decodeBinary( data )
The decodeBinary
will take a UInt8ByteArray
as parameter and gives us unzipped string. Currently only zip binary data is only supported.
data
- Data needs to be decoded and decompressed without header.
getMappedData( jsonData, mapper, cborEnable )
The getMappedData
takes 3 arguments a JSON and a map with which we will be creating a new map with keys and values mapped based on the mapper. The third parameter is an optional value to enable or disable CBOR encoding on the mapped data.
jsonData
- A JSON data.
mapper
- A Map which is used to map with the JSON.
cborEnable
- A Boolean which is used to enable or disable CBOR encoding on mapped data. Defaults to false
if not provided.
The example of a converted map would look like, { "1": "207", "2": "Jhon", "3": "Honay"}
decodeMappedData( data, mapper )
The decodeMappedData
takes 2 arguments a string which is CBOR Encoded or a mapped JSON and a map with which we will be creating a JSON by mapping the keys and values. If the data provided is CBOR encoded string the API will do a CBOR decode first ad then proceed with re-mapping the data.
data
- A CBOREncoded string or a mapped JSON.
mapper
- A Map which is used to map with the JSON.
The example of the returned JSON would look like, {"name": "Jhon", "id": "207", "l_name": "Honay"}
Shall you encounter any errors while using the APIs, please refer to the below:
Cannot read properties of null (reading 'length') - This error denotes that the string passed to encode is null.
Cannot read properties of undefined (reading 'length') - This error denotes that the string passed to encode is undefined.
byteArrayArg is null or undefined. - This error denotes that the string passed to encode is null or undefined.
utf8StringArg is null or undefined. - This error denotes that the string passed to decode is null or undefined.
utf8StringArg has incorrect length. - This error denotes that the string passed to decode is of invalid length.
Invalid character at position X. - This error denotes that the string passed to decode is invalid with an unknown character then base45 character set. Also denotes the invalid character position.
incorrect data check - This error denotes that the string passed to decode is invalid.
The below diagram shows how Inji Wallet utilises PixelPass library.
The below diagram shows how Inji Verify utilises PixelPass library.
Inji Wallet is a mobile application designed to enhance user convenience by allowing them to securely download and manage their Verifiable Credentials (VC) offline. The diagram below illustrates the extensive features of Inji Wallet, highlighting the essential modules involved in issuing Verifiable Credentials.
Furthermore, this overview outlines various user flows, detailing the seamless processes users can follow. These processes include downloading VC by utilizing eSignet for authentication, securely activating VC, logging in to eSignet, and effortlessly sharing VCs.
.
Let’s go through a brief overview these components.
eSignet: Server enables user authorization and generates Verifiable Credentials (VCs) securely from user data.
Mimoto: This is a BFF(Backend for Frontend) for routing API calls to services.
Tuvali: This is an SDK that transfers data securely over BLE following OpenID4VPBLE specification.
Biometric SDK / Face Match SDK: This is an SDK used for face verification.
Secure Key Store: This is an SDK used for key-pair generation, signing and encryption/ decryption for Android.
This is the module built for verifiers to receive VC via BLE. This is a wrapper built on Tuvali with simplified APIs.
Add a dependency in package.json
Publishing npm module is WIP. Once it's published, it can be integrated as any other npm module.
The following APIs are exposed to instantiate, start the transfer and stop the transfer
This API initializes the BLE module using the provided configuration. This initialization process allows for the sharing of configuration information for advertisement purposes. A new instance is created with each initialization.
It is recommended to use one instance per session and to initialize a new instance for each subsequent session.
The configuration passed to the constructor includes a parameter called deviceName
. This name is included in the advertisement payload during the BLE advertisement. It is important to note that this field has a character limit of 11 characters.
Signature
Parameters
This API starts with advertisement for establishing the connection
Internally interacts with Tuvali to start advertisement
Update state to Advertising
Once the secure connection is established, navigate through to state to complete the transfer
Signature
This API has to be called explicitly to stop the connection
Connection can be stopped either after successful transfer or user wants to cancel the transfer
Once the connection is disconnected, state is updated to Idle
Signature
Idle
Advertising
Connected
Secure Connection Established
Requested
Received
Error
Disconnected
Transitions between states is shown below:
Note: If either the sender or receiver decides to cancel the transfer at any stage, the state will transition to Disconnected and become Idle as a result.
This section contains the guides and information that could benefit the developers, system integrators, relying parties and the end users.
For more information on backend systems, read through:
vci-client library enables to carry out the credential request from the consumer application (mobile wallet or web) and download the VC.
Creates a credential request with access token, issuer metadata, holder jwt proof.
Provide credential response (VC) to the consumer application.
Kotlin and Swift artefacts are available to integrate with the native mobile applications.
Below sections details on the steps for integrating the Kotlin and Swift packages into the app.
inji-vc-client repo is
inji-vc-client-ios-swift repo is
Maven snapshots available
Note: implementation "io.mosip:inji-vci-client:0.1.0-SNAPSHOT"
1. Request Credential
Request for credential from the providers (credential issuer), and receive the credential.
Parameters
DownloadFailedException is thrown when the credential issuer did not respond with credential response
NetworkRequestTimeoutException is thrown when the request is timedout
An example app is added under /example folder which can be referenced for more details.
Clone the repo
In your swift application go to file > add package dependency > add thehttps://github.com/mosip/inji-vci-client-ios-swift in git search bar> add package
Import the library and use.
1. Request Credential
Request for credential from the issuer, and receive the credential response back in string.
Parameters
Exceptions
DownloadFailedError is thrown when the credential issuer did not respond with credential response
NetworkRequestTimeOutError is thrown when the request is timedout
More details
An example app is added under /SwiftExample folder which can be referenced for more details. Extract the swift example app out of the library and then follow the installation steps.
The below diagram shows how Inji Wallet utilises vci-client library.
Mimoto is a BFF(Backend for Frontend) for Inji Wallet. It's being used to get default configuration, download verifiable credentials (VC) and activate VC. It provides all necessary APIs to the Inji Wallet and acts as a proxy for resident services. Mimoto gets the request from Inji Wallet, performs all the validations and forwards it to respective services. Additionally, it subscribes to the web-sub event to be able to download the VC once it's ready.
Detailed API documentation of Mimoto is available .
To get a list of issuers, API is called. For retrieving the credential types and display properties, .well-known
location is referred for every issuer from the
Inji Wallet allows the users to download VC by redirecting the user to eSignet UI. Multiple APIs are being called to complete the process in the backend.
Inji Wallet initiates authenticate API by redirecting users to eSignet UI. On eSignet UI, user is given option to enter the unique ID, the user is asked to enter an OTP on the next screen. In the backend, token API is called to get a token. Refer for more details.
After getting a token response, Inji Wallet initiates a download request. Refer
Credentials have to be activated in order to use them for online login. When a user selects Activate option, an OTP is sent to the user and credentials are activated.
To send an OTP to a user, the below API is called.
After successful OTP validation, a keypair is generated in the phone and the public key is synced with server. The mimoto receives a certificate and create thumbprint which it stores in the keystore securely. This is called as the activation process.
The implementers can choose to use the existing configurations or add new configurations to them.
The user is currently on the +
button on the Home screen, which will open Add new card
screen, where all the issuers are displayed Below issuers list API gives out all the issuers list
To get complete configuration of the specific issuer, below api is called.
The eSignet service is utilized by Inji Wallet for online login and downloading the VC. Users have the ability to log in to any service provider portal that is integrated with eSignet.
The user is required to open the portal integrated with eSignet and utilize the app scanner to scan the QR code.
After successfully scanning the QR code, Inji Wallet will access the API below and transmit the link code.
After successfully completing the offline face authentication and selecting the required and optional information, the two specified APIs are invoked.
The user is currently on the Add new card
screen and chooses the option to Download via eSignet
.
Inji Wallet utilizes the react-native-app-auth
library to authorize and redirect the user to the eSignet user interface. The configuration for redirection is retrieved as part of the issuer's configuration.
Once the user is on the eSignet user interface, they input the necessary information such as a unique ID and OTP (One-time Password). After entering the OTP, the user is redirected back to Inji Wallet in order to generate a key pair and initiate the request to download the credential.
For credential request, refer credential_endpoint attribute in issuer's configuration response.
This is a draft specification that is used to implement the face match in the Inji Wallet or any similar wallets.
This API is asynchronous and can be used for initializing the implementer's SDK. During initialization, the implementers can use this API to build logic to validate the license, download the latest model file if needed, or inform the server about its usage. This API is expected to return errors when there is a critical issue with the initialization process. If the API is called more than once, then the SDK can optionally return based on the current status. The implementation of this API should support offline mode. In offline mode, the implementor should ensure smooth usage. Care should be taken by the implementor to ensure the SDK is lightweight and does not slow down the app.
The implementation of this API should immediately return if initialization has already been completed.
The implementation should not attempt to initialize multiple times unless it's necessary.
The implementation should work in offline mode.
The implementation should support auto-downloading the latest models or any other configuration/artefacts necessary.
To enhance logging and traceability, the implementer should accept a parameter known as traceabilityId
, which helps to trace the logs on the server.
Signature
Inji Wallet would initialize the config as a JSON. The JSON would contain the following items
Standard Return Codes (true or false)
An asynchronous API that compares two images, allowing for different image formats such as PNG, JPG, HEIC or Template. Upon completion returns a boolean value. The API has an expected timeout and it is expected that the implementors clear the memory and processing upon timeout.
To enhance logging and traceability, the implementors should send telemetry using traceabilityId
. The id is set during the configure API call, It is expected that the same is used here. In Inji Wallet, AppId
is used as traceabilityId
.
Timeout is set in seconds.
Signature
Parameters
Standard Return Codes (match or no match)
The following guidelines apply to individuals who are developing the face SDK:
It is prohibited to collect any personally identifiable information (PII) or phone details.
Inji Wallet includes built-in telemetry, and all telemetry data must be transmitted to the designated system. Telemetry enhances Inji Wallet's observability features by capturing specific events, creating measures, and monitoring various user actions and events.
Recording or transmitting IP addresses, user details, Phone IMEI, phone numbers, or user photos in telemetry or logs is strictly prohibited
The use of device fingerprints should be limited to managing the SDK license.
Snapshot builds are available .
Name | Type | Description | Sample |
---|
Name | Type | Description | Sample |
---|
The configurable properties for mimoto can be found at . This property file is maintained as one for each deployment environment. On repository, each environment configuration is placed in a corresponding branch specific to that environment.
Refer to of Collab environment.
To ensure fraud prevention in compliance with , the faceAuth verification should include passive liveness checks, such as picture-in-picture.
Name
Description
ConfigOptions
configOptions
device name used during advertisement
deviceName is the parameter
issuerMetaData | IssuerMetaData | Data object of the issuer details | IssuerMetaData(credentialAudience, credentialEndpoint, downloadTimeout, credentialType, credentialFormat) |
proofJwt | Proof | The proof used for making credential request. Supported proof types : JWT. | JWTProof(jwtValue) |
accessToken | String | token issued by providers based on auth code | "" |
issuerMeta | IssuerMeta | struct of the issuer details like audience, endpoint, timeout, type and format | IssuerMeta(credentialAudience, credentialEndpoint, downloadTimeout, credentialType, credentialFormat) |
proofJwt | Proof | The proof type ProofJwt ex jwt | JWTProof(jwt: proofJWT) |
accessToken | String | token issued by providers based on auth code | "" |
Name | Description | Type |
config | Configuration with model file and matcher threshold | Any object |
Attribute Name | Description |
traceabilityId | Traceability id is used to trace the telemetry data |
io.inji.sdk.* | Any configuration that starts with io.inji.sdk would be sent in the config map. |
Response | Status |
true | Success |
false | Error |
Response | Status |
true | Matched |
false | Not Matched |
false | Error |
Name | Description | Type |
timeout | Timeout in seconds. After this time the SDK should stop processing. | integer |
capturedImage | The image that is captured by the camera |
vcImage | The image that is given in the VC |
format: data:image/ base64 encoded image eg: data:image/jpeg
format: data:image/ base64 encoded image eg: data:image/jpeg
This API provides data with search capability to populate the list of supported issuers in Inji Web, which is then displayed under the List of Issuers
OK
This api is used to generate otp for wallet binding. This api is used as a proxy to call Identity Provider - Send Binding OTP Endpoint api internally.
The individual id. UIN or VID.
Otp channels using which user will be notified, for example - EMAIL, PHONE
OK
The masked email of user
the masked mobile of user.
This API provides the complete configuration details for the specific issuers passed in the path variable
OK
This api is used to bind the credential with wallet. This api is used as a proxy to call Identity Provider - Wallet binding Endpoint api internally.
The request time
Auth factor type to be binded for the provided key.
Format of the auth factor type supported in the wallet app. Right now Inji supports only jwt.
The individual id. UIN or VID.
The public key of the wallet app.
Defines the type of auth challenge. It should be same as authfactor.type (oauth-details response).
Actual challenge as string. A jwt in case of inji.
Format of the challenge provided.
OK
Server certificate after successful binding. This certificate will be stored in wallet app.
the wallet binding id in encrypted format. The wallet app will associate the requested credential with this id.
expiry date time of the binding.
the certificate thumbprint.
the certificate key id.
Once the authentication is successful and user consent is obtained, this endpoint will be invoked by the wallet app to send the accepted consent and permitted scopes.
yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
Transaction id echoed starting from /authorize call.
List of permitted scopes by end-user.
List of accepted essential and voluntary claims by end-user.
OK
This is the same transactionId sent in the link-transaction response.
Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the Wallet-app, this endpoint will be invoked from wallet-app.
Supported auth-challenge depends on the integrated authentication server.
On Authentication Success: Only linkTransactionId is returned in the below response without any errors.
On Authentication Failure: Error list will be set with the errors returned from the integrated authentication server.
yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
This is the same transactionId sent in the link-transaction response.
User identifier (UIN/VID).
Authentication Challenge.
Defines the type of auth challenge. It should be same as authfactor.type (oauth-details response).
Actual challenge as string.
Format of the challenge provided.
OK
This is the same transactionId sent in the oauth-details response.
List of Errors in case of request validation / processing failure in Idp server.
The link transaction endpoint is invoked from Wallet-app.
Validates the link-code and its expiry and generates the linkTransactionId. This linkTransactionId is linked to transactionId returned from /oauth-details endpoint.
Returns the auth-factors, clientName, logoUrl, User claims, authorize scopes along with linkTransactionId.
Note: Wallet-app will hereafter address the transaction with this linkTransactionId for the /authenticate and /consent endpoints.
Link code as received by the wallet-app from the QR code scanning.
OK
Unique link-transaction-id.
Registered name of the OIDC client.
Registered OIDC client Logo URL.
List of requested scopes to be permitted by the end user.
List of client request mandatory claim names.
List of client request optional claim names.
Auth factors defines the authentication screens displayed in IDP frontend. More than one authFactor may be resolved or combination of auth factors. Precedence of authFactors is based on its order
Name of the authentication method
Applicable for biometric based authentication, number of bio segments to be captured for authentication.
Applicable for biometric based authentication. Can be more specific about which bio segments should be captured.
Once the access token is received via the token endpoint, Wallet should invoke this endpoint to get the verifiable credential.
Format of the Credential to be issued.
JSON object containing proof of possession of the key material the issued Credential shall be bound to.
The proof object MUST contain a proof_type claim of type JSON string denoting the concrete proof type.
When proof_type is jwt, a proof object MUST include a jwt claim
When proof_type is cwt, a proof object MUST include a cwt claim
JSON object containing (and isolating) the detailed description of the credential type. * This object MUST be processed using full JSON-LD processing. * It consists of the following sub claims: * @context: REQUIRED. JSON array * types: REQUIRED. JSON array. This claim contains the type values the Wallet shall request * in the subsequent Credential Request.
OK
JSON string denoting the format of the issued Credential.
Contains issued Credential. MUST be present when acceptance_token is not returned. MAY be a JSON string or a JSON object, depending on the Credential format.