Only this pageAll pages
Powered by GitBook
1 of 76

v3.8.x

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Core

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Token

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Truststore

Loading...

Loading...

Loading...

Payment

Loading...

Loading...

Loading...

FIle

Loading...

Loading...

Loading...

HSM

Loading...

Other

Loading...

Loading...

Loading...

Miscellaneous

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Installation Manual

Loading...

Loading...

Release Notes

Loading...

Introduction

Trust1Connector v3 Documentation

A Word of Introduction

The Trust1Connector Javascript SDK is a library that functions as a proxy towards the Trust1Connector API. This Library does not contain any business logic and is a refernce implementation for the Trust1Connector API (HTTP/JSON).

Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks which are also available on the Trust1Connector Javascript SDK.

The Trust1Connector is a middleware which interacts with hardware tokens and system certificate stores (where certificates are stored and protected within the operating system).

Trust1Connector's ambitions

The ambitions of the Trust1Connector is to:

  • provide a generic interface to hardware tokens and smart cards

  • operating system agnostic (works for all operating systems)

  • browser agnostic (not depending on a browser plugin)

  • facilitate the onboarding and identity dematrialization

  • facilitate the derivation towards a mobile identity

  • favours a decentralized approach and privacy-first

  • facilitate user authentication and digital signatures

  • facilitates identity information validation and secured transport

  • favours a approach

  • exchange

Zero-Knowledge
Verifiable Claims

Trust1Connector JS SDK

You can find the trust1connector JS SDK for the Trust1Connector v3 via NPM

You can also find the source code here

https://github.com/Trust1Team/t1c-sdk-js/tags

Concept

Running the Trust1Connector in a shared environment, such as Citrix, XenApp and Remote Desktop, requires additional installation steps. In this section we explain the concept and approach used.

Architecture Overview

The following schematic seems rather complicated as it explains the inner workings of the Trust1Connector components, the concept is explained further on this page. If you are only interested in what the integration impact is for your Web Application in a Shared Environment, you can skip and go directly to the following section:

Components

Web Environment

The Web Application can use the T1C-SDK-JS or a custom REST API client for integration purpose. As the Web Application operates in a browser context, resolving an agent, by means of a consent, will result in a browser cookie being provided.

The T1C-SDK-JS implements the detection of a Shared Environment during the initialisation of the library. When initialisation succeeds without a controlled exception, the setup is a standalone; when the initialisation throws an 401 Error, the T1C-SDK-JS can be used to request the user for a Consent.

When using the REST API directly form your web application, reading the browser cookie and performing the initialisation must be done by the integrating Web Application itself.

Shared Environment Host process [t1c-registry]

Compared to Trust1Connector v2, the v3 release has a separate component to be be installed on a shared host. This component is called the T1C-Registry and only exposes the following use cases:

  • Verify random available ports [in a predefined range] which can be used by an Agent (Session of T1C-API running in user space)

  • Port reservation upon installation of a new T1C-API in an active user session

  • Port registration upon initialisation of a T1C-API in an active user session

The T1C-Registry operates by Default on the API port defined in the T1C-DS (Distribution Server). From a Web Application perspective, this is the only information known. When a Web Application requests the information of the device, the PROXY device type will inform the Web Application that the targeted underlying API is a PROXY, which means that the Web Application must ask for the Agent specific API port to configure an URI which can be used to execute the use cases.

When using the T1C-SDK-JS this is done implicitly during initialisation.

A T1C-API installed for a specific users runs in [User Space]. To avoid possible attack vectors, the Trust1Connector v3 will always run in [User Space].

Upon installation of the T1C-API, during the post install phase, the T1C-API will try to verify automatically if it is running in a shared environment. If this is the case, the T1C-API will ask the T1C-Registry for available ports and will reserve those post, prior to initialisation and startup.

The ports which are reserved by the T1C-Registry are the following:

  • T1C-API Port: This is the port exposing the OpenAPI interface towards Web Applications and used by the T1C-SDK-JS

When receiving ports during post-install, an user agent device is temporary RESERVED in the Agent Registry of the T1C-Registry. Upon T1C-API initialisation, the port configurations will be confirmed and the Agent Registry will set the device state on REGISTERED. From this moment on, a T1C-API instance, running in an active user session, will be available for the Web Application via the .

The T1C-sandbox instance is inherently a component from the T1C-API, and thus is managed by the T1C-API. As each user must have it's own hardened runtime for communication purpose, the port assigned for T1C-sandbox will be registered and configured by the T1C-API (and restarted when needed).

Starting from this release (v3) of the Trust1Connector, each device must have a link with an active and running T1C-DS (Trust1Connector Distribution Server). This is to guarantee security, updates, and avoid potential risk in production.

The T1C-DS is proceeded by an API Gateway who is managing the security offloading in the application layer. For a Web Application to communicate with a T1C-Registry or T1C-API, a JWT (Json Web Token) is needed and obliged. The T1C-DS is responsible for the key management, the certificate management and other use cases which are described in a separate wiki.

In order to retrieve a valid JWT, the T1C-DS can be requested from your application back-end with a valid api-key. The JWT is valid for a given amount of time, and sets the context used when requesting the T1C-API on a device.

The PIN handling logic is implemented in the Trust1Connector API. More information on the basic and/or advanced rules can be found on the following link:

Management of an in-memory list of active Agents
  • Management of user consents in a shared environment by means of browser cookies with an optional configurable TTL (time to live)

  • Shared Environment Client process [t1c-api]

    Central Back-Office

    Security

    Pin Handling

    Share Environment Flows

    Communication Stack

    Integration in Web Applications
    consent flow

    Prerequisites

    Trust1Connector API DNS

    The Trust1Connector API v3 exposes a secure REST API on the client device. Trust1Team has created a t1c.t1t.io DNS entry (or customer-specific DNS entry) that points to 127.0.0.1 in order to facilitate SSL communication. This means that if the customer infrastructure uses a proxy for all network traffic, an exemption must be made for t1c.t1t.io to always point to the origin device's loopback address. The same holds true for the localhost domain name, this should redirect to 127.0.0.1 on the user's local system, not the localhost of the proxy server.

    If no exemption is made and https://t1c.t1t.io is handled by a proxy, it will redirect to 127.0.0.1 IP of the proxy server instead of the local machine, and the Trust1Connector API will be unreachable.

    The reserved domain from Trust1Team (t1c.t1t.io) has been registered with DNSSEC on the aforementioned URI. When a PARTNER uses its own DNS, we strongly recommend applying DNSSEC on the domain used in production.

    Some (corporate) networks have a policy that disables the ability to bind a domain to a local network IP. The Trust1Connector relies on this for t1c.t1t.io which resolves in to 127.0.0.1 which is a local ip for localhost

    If DNS rebind protection is enabled it is unable to use t1c.t1t.io for connection towards the Trust1Connector because the network does not allow this Domain to be a local ip-address.

    To resolve the issue either DNS rebind protection can be disabled or you can whitelist the domain t1c.t1t.io to allow this domain.

    Applications that want to make use of the Trust1Connector will be run from a specific domain. This means that the Trust1Connector needs to know that certain domains/applications want to make use of the Trust1Connector's functionality.

    For these applications to gain access to the Trust1Connectors API we need to whitelist the domain in whats called the cors list. This list contains all the accepted domains that can make use of the Trust1Connector.

    In order to correctly function, the Trust1Connector API must be able to connect to its configured Distribution Service. You must allow REST traffic to the following URLs (if applicable):

    • Acceptance: https://acc-ds.t1t.io

    • Production: https://ds.t1t.io

    A partner can opt for its own Distribution server, whereas the URIs mentioned above, will be defined by the hosting party.

    In some cases (environments) the Domain acc-ds.t1t.io or ds.t1t.io are not accessable. If this is because the domain cannot be resolved we do recommend to either ask the network/system administrator to make sure that those domains can be resolved on the network. Or changing the DNS server to the google DNS (8.8.8.8 & 8.8.4.4), this has solved the issue for some of our customers.

    Trust1Connector installer is about 20Mb in size. The installed size comes to 40-50Mb.

    This includes the Trust1Connector API, Registry and Sandbox.

    Trust1Connector installer is about 20Mb in size. The installed size comes to 40-50Mb.

    This includes the Trust1Connector API, Registry and Sandbox.

    The increased size over windows mainly comes to the way MacOS handles dialogs. These are distributed with the Trust1Connector as seperate binaries.

    All endpoints of the Trust1Connector API are secured and require a JWT to access. To obtain a token, an .

    This API key must be requested from TRUST1TEAM, or created by the customer if they are hosting their own Distribution Service. The API key must never be used in a front-end application (where the API key can be compromised). The API key is needed to exchange the token, using a Distribution Server, resulting in a short-lived Json Web Token.

    A PARTNER can decide to distribute a version without the use of a JWT. In those cases, the liability of the security flow resides completely in the context of the web application, thus Trust1Team can not guarantee the security context where the Trust1Connector is integrated upon.

    Trust1Connector support two operating systems for all tokens, Linux (Debian/Ubuntu) for PKCS11 tokens; On request, a Google Chromebook can be supported depending on the deployment or target installer.

    • MacOS 11.x or higher

      • X86 architecture

      • M1/M2/ARM architecture

    Trust1Team support Windows/Mac OSX OS families where lifecycle support is guaranteed from the Vendor of the Operating System. The moment the OS version has been marked as ‘end of life’, Trust1Team can not guarantee the functionality anymore.

    When PARTNERS are in need to support an older version or keeping the support running on the level of Trust1Team, no guarantees can be made. Trust1Team can setup a custom project, on demand of the PARTNER. Those requirements, changes or other adaptations needed, are not covered in the Trust1Connector license fee.

    Supported OS or platform
    Supported
    Remarks

    To run in user-space on Windows 8.1 or higher some components have to be set on the operating system

    Below you can find a list of all registry keys that will be created for the working of the Trust1Connector, All these keys are added to HKCU

    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

    HKEY_CURRENT_USER\SOFTWARE\Trust1Team\Trust1Connector

    Since 3.5.x no more cookies are used.

    The Trust1Connector is browser agnostic so it does not matter what browser is being used as long as it support HTTP communication (HTTP 1.1) (which should all of them).

    Version wise we do recommend to use the latest versions of your browser for security reasons but the versions below is was we accept as a minimum

    • Chrome >80

    • Firefox >75

    • Edge 88 or higher

    Windows 810 or higher

    EOL but some partners are running a custom compiled target of the Trust1Connector in production until migration.

    Windows 10

    Yes

    Windows 11

    Yes

    macOS 10.15 (Catalina)

    No

    EOL

    macOS 11 (Big Sur)

    No

    EOL

    macOS 12 (Monterey)

    No

    EOL

    macOS 13 (Ventura)

    Yes

    macOS 14 (Sonoma)

    Yes*

    macOS 15 (Sequoia)

    Yes

    IE 11 (End of Life is June 15 2022)
  • All other browsers. As recent as possible

  • Windows 7

    No

    EOL but some partners are running a custom compiled target of the Trust1Connector in production until migration.

    Windows 8.1

    DNS rebind protection

    Applications using the Trust1Connector

    If you want to use the Trust1Connector on a specific domain, please contact our support team to add this domain to the cors list.

    Distribution Service

    Disk Space

    Keep in mind sizes can vary a bit depending on the Operating system and the environment (develop, acceptance, production)

    Windows

    MacOS

    API Key

    Operating System

    2023-10

    macOS 14 (Sonoma) has issues at the moment with usblib and CCID. A future patch will fix the card reader issues; Updates will be come avaible when a patch is released

    Windows 8.1 or higher

    Registry keys

    Cookies

    Browsers

    API key must be exchanged

    No

    Reference
    Reference
    Reference
    Reference
    Reference
    Reference

    Readers

    Introduction

    The Trust1Connector after correct initialization has the ability to retrieve the available card readers detected on the system. With these card readers you can continue and execute functionality such as retrieving biometric information, signing data, authentication, ...

    Below you can find more information on how to retrieve the available readers. All these functions are available in the Core Service

    List card readers

    Returns a list of available card readers. Multiple readers can be connected. Each reader is identified by a unique reader_id.

    T1CSdk.T1CClient.initialize(config).then(res => {
        var coreService = res.core();
        core.readers(callback);
    })

    The response will contains a list of card readers:

    {
      "success": true,
      "data": [
        {
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false,
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card (eID)"
            ],
            "module": ["beid"]
          }
        }
      ]
    }

    When multiple readers are attached to a device, the response will show all connected card readers:

    {
      "data": [
        {
          "id": "ec3109c84ee9eeb5",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(2)",
          "pinpad": false
        },
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ],
            "module": ["beid"]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        },
        {
          "id": "c8d31f8fed44d952",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(1)",
          "pinpad": false
        }
      ],
      "success": true
    }

    Important to notice:

    • The response adds a card-element when a card is inserted into the card reader.

    • The response contains card-reader pin-pad capabilities

    As mentioned in the List card-readers, when a smart-card is inserted/detected, the reader will contain the cart-type based on the ATR. The ATR (Anwser To Reset), is the response from any smart-card when powered, and defines the card type. The Trust1Connector recognized more than 3k smart-card types.

    In the response below you notice that this specific card also includes a module and description property. Both of these are arrays and are also optional. This means that the Trust1Connector recognizes this specific token and knows which module can be used for this token. The Trust1Connector has the possibility to detect that a card can be used by more than 1 module, in that case the module array will display multiple values depicting which modules can be used. The description is purely metadata.

    As mentioned, when a card-reader has pin-pad capabilities, this will be mentioned in the response (notice the pinpadproperty):

    The following example is the response for List card-readers on a device with 4 different card-readers attached:

    In the above example you notice that 4 card-readers are connected. Each card-reader receives his temporary id which can be used for other functions where a card-reader id is needed. This method can be requested in order to list all available card-readers, and optional cards-inserted. Each card-reader has a vendor provided name, which is retrieved from the card-reader itself. An additional property pinpad, a boolean value, denotes if the card-reader has pin-pad capabilities. A pin-pad is a card-reader, most of the times with its own display and key-pad. From a security perspective, it's considered best practice to use as much as possible pin-pad capabilities of a pin-pad card-reader.

    When a reader has a smart-card inserted (contact interface) or detected (contactless interface), the card type will be resolved by the Trust1Connector in order to respond with a meaningful type. In the above examples you see that; one card-reader has a Belgian eID card; another card-reader has a MisterCash or VISA Card available for interaction.

    Possibility to exclude certain readers based on their name. the input accepts a comma separated list if multiple exclusion terms are needed

    Returns a list of available card readers with a smart card inserted. Multiple readers can be connected with multiple smart cards inserted. Each reader is identified by a unique reader_id and contains information about a connected smart card. A smart card is of a certain type. The Trust1Connector detects the type of the smart card and returns this information in the JSON response.

    Response:

    Card Inserted

    Pin-Pad Capabilities

    List Card-Readers - Explained Example

    Exclude readers

    This exclude readers will search for the term in the reader names and exclude those that match with the term

    Get card readers with card inserted

    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ],
            "module": ["beid"]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    {
      "data": [
        {
          "id": "ec3109c84ee9eeb5",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(2)",
          "pinpad": false
        },
        {
          "card": {
            "atr": "3B67000000000000009000",
            "description": [
              "MisterCash & Proton card",
              "VISA Card (emitted by Bank Card Company - Belgium)"
            ],
            "module": ["emv"]
          },
          "id": "e5863fcc71478871",
          "name": "Gemalto Ezio Shield Secure Channel",
          "pinpad": true
        },
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
            "module": ["beid"]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        },
        {
          "id": "c8d31f8fed44d952",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(1)",
          "pinpad": false
        }
      ],
      "success": true
    }
    T1CSdk.T1CClient.initialize(config).then(client => {
        var core = client.core();
        core.readersExcludeByName("Bit4id,hello", callback);
    }, err => {
        console.error(err);
    });
    {
      "data": [
      ],
      "success": true
    }
    T1CSdk.T1CClient.initialize(config).then(client => {
        var coreService = client.core();
        core.readersCardAvailable(callback);
    }, err => {
        console.error(err);
    });
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": []
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }

    Release Notes

    v3.8.8

    Release 02/12/2024

    Improvement

    • add static compilation for MSVC (vc runtime)

    • update sandbox linker (robustness)

    v3.8.7

    Release 02/12/204

    New Features

    • VDDS Medical module

    • Update tracing

    v3.8.6

    Release 21/08/2024

    Fix the blocking SSL download at startup (DS communication)

    Add flag to check SSL certificate on startup

    v3.8.4

    Release 06/06/2024

    Simplesign SDK-JS points to wrong endpoint

    Document host file issue

    As a user I want to get the version available for the Belgian eID

    Detect DNS Rebind and fix by asking user to allow update of the local host file

    As an integrator I can ask for all readers and ask to exclude readers by name

    v3.8.3

    Release 29/05/2024

    Update the SimpleSign bootstrap filename to the original

    v3.8.2

    Release 22/05/2024

    As an integrator I want correct error codes when cancelling the pin action on Sign, Authenticate or verify pin actions

    As an integrator I want correct error codes when timeout the pin action on Sign, Authenticate or verify pin actions

    As an integrator I want access to the SimpleSign module

    v3.8.1

    Release 19/03/2024

    Implement Pkcs11 module

    v3.8.0 🎉

    Release 21/02/2024

    Bug

    Update T1C SSL certificates when running binaries from user session, while binaries are located in admin location

    Apple al-tool deprecation for signing/notarization

    Allow t1c-sdk-js to initialize using multiple endpoints

    Cleanup certificates interfaces

    Allow sdk initialisation with multiple hosts, selecting first-to-respond

    v3.7.13

    Release 19/02/2024

    GetReaders does not return a suggested module, it only does it when using GetReaderS

    When DS /download/ssl is not available -> api does not start (panic due to unwrap) :-)

    Prevent REG from running when a local process has been deteced!

    Update the T1C with the new SSL for DNS t1c.t1t.io

    Update system crate

    v3.7.11

    Release 30/10/2023

    Shared environment - issue with 904300-Signature data does not equal the expected data: reg should not send out the signature in the responses (or verify if the client pub is correctly loaded for REMOTE environments) -> local is not an issue

    Apple al-tool deprecation for signing/notarization

    Direct download of SSL when digest is not equal to the published version on DS

    Add the integration with Local Signing Application

    v3.7.10

    Release 03/10/2023

    t1c-sdk-js make excessive failing "pre-flight" requests

    Ds Logs push using CURL has issues -> not sending over the PUT json body

    File exchange list content type on macos sometimes gives read access errors on a just created folder via the API

    SSL certifiicate synchronisation does not happen after first startup

    v3.7.9

    Released 26/07/2023

    Release notes

    Validate and consent Lock error on mutex should not return invalid consent but should give a propper try again later error

    As a system administator I want to see the transactions of devices - somehow the transactions don't reach the DS

    Prevent the refresh needed when polling during connector update/upgrade

    Add version to the installer

    v3.7.7

    Released 30/05/2023

    Release notes

    JWT token validation consistently fails due to incorrect device time

    As a DS I need to provide a JWT token based on the time information of the requester.

    Pass through the optional lable from the JWT SUB to the transactions file and DS

    As a system I should be able to send the log files to the DS so that support can easily look for issues with a device

    v3.7.5

    Released 18/01/2023

    Release notes
    • After registering the device a synchronisation needs to happen

    v3.7.4

    Released 22/12/2022

    Release notes
    • Upgrade compiler version to latest stable

    • As a system I when installed in a separate folder I want to validate the SSL certificate validity and domain based on the root file

    v3.7.2

    Released 20/10/2022

    Release notes

    Story

    • As a system I should be able to send the log files to the DS so that support can easily look for issues with a device

    v3.7.1

    Released 20/10/2022

    Release notes

    Bug

    • Remove header that was added in 3.7.0 from testing APN (w3c draft) implementation which caused older versions to fail

    v3.7.0

    Released 19/10/2022

    Release notes

    Bug

    • Registry does not retrieve the base cors list on startup

    • Mutex lock causes Registry and api to go into a deadlock

    🔺Mutex

    The API and Registry use a feature called Mutexes to have data that can be shared over multiple OS threads. Using this is necessary for some functionality. In previous versions when you have a Shared environment (citrix for example) you could make the API and Registry get into what's called a DeadlockThis caused the Mutex to never be unlocked for use by another OS thread. Causing the connector to be blocked completely.This has now been solved and has been tested on instances of 1000 concurrent devices.

    🔺System time out of sync

    We had a user which Operating system had a custom date set (not synced) which caused issues with DS communication. The DS communication also checks wether the time of request is not in the future or in the past (with some slack ofcourse). So if you use the Connector with a custom date you will not be able to contact the DS because it requires a request within a correct time-zone.If this is not the case it could be that a malicious user is trying to exploit the DS at which point the DS refuses the request. The issue was that this caused the Connector to crash.This has been solved so that the Connector does not crash.System time must be correct, otherwise DS communication can not be done (secrity issue)

    Private Network Access is a new CORS draft. Which prevents remote servers to contact local instances without any extra checks. Chrome has already implemented this draft in a non-blocking manner, the implemenation of chrome is to send 2 pre-flight requests. One which is the normal pre-flight and another one where the PNA implementation has been done.At this point the pre-flight for the PNA implementation is non-blocking meaning that if the pre-flight fails it will not block the request.When the PNA Cors draft is final this will become blocking.In this release we've already started adding some required components to support this in an upcoming release.

    In this release we've implemented a feature where the Connector will send it's log files towards the DS. This is so that support desks can easily get the log files of the device which is requesting support.

    We've added a feature where you can run the Connector in regualr HTTP mode. To still be secure we've added a signature field to the responses which can be verified to not be tampered with at the client's side. This verification is implemented in the JS SDK.

    The consent error code has been updated in the Trust1Connector API library, and t1c-sdk-js clients have no impact on that change

    When using different instances of the Trust1Connector (optionally from another partner) on a Windows system, a port collision could be possible due to a race condition in port assignment upon initialization. Ports are now protected with anti-collision and are salted to make a port less guessable.

    When no LaunchAgents folder was present on the system, the installation procedure creates this folder implicitly.

    Camerfima is a new PKCS11 token added to the modules of the Trust1Connector. The Camerfirma token pre-requisites the installation of the Carmerfirma middleware.

    Chambersign is a new PKCS11 token added to the modules of the Trust1Connector. The Chambersign token pre-requisites the installation of the Chambersign middleware.

    The token info endpoint has been implemented before only for identity tokens. We have added support for Token Info of the PKCS11 modules. As the response has a different data structure, an additional type has been added for clients to parse the response correctly.

    The PKCS11 token info exposes information on the algorithms which can be used for different use cases (digital signature, validation, authentication, ...). In a future release additional functionality will be provided such as: encryption, decryption, key exchange,...

    For the different notification types, many tokens share multiple certificates for a single type. The original interface supported only a single certificate response. To be backwards compatible, those certification function have been adapted to be behave the same as in v3.5.x.

    New functions are available to support multiple certificate reponses, they are called: [certificateType]Extended. For PKCS11 tokens the certificate response also returns, besides the base64 encoded certificate and the certificate id, the following properties:

    • issuer

    • subject

    • serial number

    You can find an example for

    A new function has been added for all PKCS11 modules called the 'validate' endpoint. This endpoint, when available, can be used to validate a signed hash received after calling the 'sign' function. In an next version a variant of the validation function using OpenSSL will be added for all tokens.

    For the Trust1Connector to support more PKCS11 functionality, the intermediate PKCS11 layer has been removed in preference of a direct PKCS11 LIB integration. FFI is used in RUST to support any library which need to be loaded.

    Additional guard has been implemented to prevent empty algorithms for the digital signature and validation endpoints. PKCS11 tokens will verify as well if the provided algortihm is exposed as an allowed mechanism for the targetted use case.

    The Trust1Connector can now detec Java Card Object Platform 3 typed cards

    When requesting for a signature or an authentication, the correct certificate must be provided. For PKCS11 tokens the certificate id (or reference) can be ommitted. The PKCS11 token will be default pick the first certificate (for the type needed) and use this with the specified mechanism to sign/authenticate.

    hash sub pub key
  • hash iss pub key

  • exponent (payment modules)

  • remainder (payment modules)

  • parsed certificate (ASN1 format of the base64 encoded certificate)

  • disable default DNS rebind (will be added in UI component in future versions, can be overriden using t1c-launc fix-dns-rebind

    Update command exec functionality

    DNS Rebind check + dialog to fix it with admin rights

    T1C-2886 T1C SDK JS, retrieve reader list should exclude windows hello for business

    T1C-2852 Implement Truststore Certificates interface

    T1C-2853 Implement Truststore Transactions interface

    T1C-2854 Add global x509 utility endpoints for certificate parsing (DER|PEM|x509)

    T1C-2855 Remove deprecated proxy url and port from SDK initialization

    T1C-2856 Remove PKI.js dependency (replaced with the addition of API x509 endpoints

    T1C-2857 Add parsing of certificates into Subject or Issuer CN

    T1C-2858 Impelementing reader and truststore cross-over model

    T1C-2859 Adding Keychain integration for Mac OSX

    T1C-2860 Adding MSCAPI (wincrypt) and CNG for Windows

    T1C-2809 Sidecar for Certificate check upon start and init

    T1C-2810 Add swagger-ui initial set of exposed apis

    T1C-2812 Provide an initial openApi spec for LSA module

    T1C-2638 As an integrator I can ask T1C to digest data before sign for each module

    Update T1C SSL certificates when running binaries from user session, while binaries are located in admin location

    T1C-2671 Update notarization in packager, altool being deprecated

    T1C-2755 RMCR - Upgrade sentry to latest version

    T1C-2760 Document Dashboard setup

    T1C-2380 As a User/Support desk I would like to change the log-level (info|debug|warn)

    T1C-2652 As a System I need to keep my transactions between installations

    T1C-2805 Update Cryptoki on Mac/Win for updated PKCS11 drivers

    Upgrade Rust Edition 2021

    T1C-2779 Update Clap

    T1C-2781 As a connector running on a local device I want to support key rotation from the application consumer

    T1C-2782 Update clap to v4 as CLI parser

    T1C-2783 Enable insecure for debugging when running in dev mode

    T1C-2784 Update the token information returned to the web application to contain a valid type

    T1C-2785 Finalise PKCS11 session for each running instance when ending a remote transaction

    T1C-2786 Update the PNA specification as an extension on previous release (announced Google Chrome v117)

    T1C-2787 Add documentation for ReadMyCards Web Application used for demonstration and showcase

    T1C-2790 Upgrade utility libs

    T1C-2791 Initial version for an independant debugger

    T1C-2789 Add tracing events to the connector api and registry

    As a client of the T1C API I want the api to validate the JWT token sent before proceeding with the use case

    T1C-2696 As a T1C API I want to renew the certificate needed for validation of the JWT when rotation happens on the DS

  • When the user has a custom date/time set on his System it causes the API to crash on DS communication

  • Shared environment/multi user setup makes the Registry and API get in a deadlock state

  • Vulnerabilities based on Penetration test of Connective

  • Improvement

    • Use separate endpoint for reg to validate if api is registered on the correct user

    • As an integrator I can ask for all readers and ask to exclude readers by name

    Story

    • As a system I want to use the private and public device key to encrypt and decrypt the response data so that an integrator/SDK can validate that no man in the middle attack has happened

    ✅ Private Network Access

    ​☑️ Sync log files with DS

    ​☑️ HTTP verify response signature

    v3.6.3

    Released 19/08/2022

    Release notes

    Bug

    t1c-sdk-js tries to validate any present consent token when consent is disabled (optional consent)

    Improvement

    Remove the implicit CORS request from API info endpoint to DS, and provide/expose a public function in JS for application to force a CORS sync

    Story

    As a dashboard user I want to see how many installation have the DNS rebind issue

    v3.6.1

    Javascript SDK 3.6.0 has been unpublished and contains a bug in the consent flow where the error code is not returned correctly

    Released 01/04/2022

    The Mac Silicon (M1) is not yet supported for this version

    Release notes

    Bug

    • Update consent error codes for 3.6.x so that they do not interfere with other error codes

    Improvement

    • As an SDK integrator I want to be able to fetch all the certificates on a token, including their information

    • As a user I want to validate the signed hash from a PKCS11 token, using the validation function of the PKCS11 interface

    • As a user I want ot use Camerfirma token

    • As a user I want to use Chambersign token

    • As a SDK integrator I want to be able to call the TokenInfo enpdoint on PKCS11 tokens

    🔺 Consent error code update

    🔺 Multi-client support and race condition fix

    🔺 Implicit creation of LaunchAgents folder on Mac/OSX

    ☑️ Exposed Camerfirma interface

    ☑️ Exposed Chambersign interface

    ☑️ Token Info endpoint will now returned detailed information when using a PKCS11 token

    ✅ Fetch all the certificates on a token including all their information

    ✅ Signed hash validation function exposed for PKCS11 tokens

    ✅ PKCS11 migration towards RUST

    ✅ Token Algortihm input validation for signing and authentication

    ✅ JCOP3 ATR added

    ✅ Select default PKCS11 non-repudation or authentication certificate

    Bug

    Improvement

    Release notes - Trust1Connector - t1c-sdk-js_v3.8.4

    Bug

    Task

    Story

    Improvement

    Release notes - Trust1Connector - t1c-rust-api_v3.8.3

    Bug

    Release notes - Trust1Connector - t1c-rust-api_v3.8.2

    Bug

    Story

    Story

    Task

    Story

    Improvement

    Bug

    Task

    Improvement

    Release notes

    Bug

    Task

    Story

    Release Notes

    Bug

    Bug

    Task

    Bug

    Story

    Improvement

    Bug

    Task

    Story

    certigna here
    T1C-2900
    T1C-2899
    T1C-2888
    T1C-2866
    T1C-2889
    T1C-2894
    T1C-2717
    T1C-2890
    T1C-2883
    T1C-2884
    T1C-2885
    T1C-2863
    T1C-2804
    T1C-2777
    T1C-2820
    T1C-2843
    T1C-2851
    T1C-2800
    T1C-2827
    T1C-2846
    T1C-2819
    T1C-2845
    T1C-2806
    T1C-2777
    T1C-2560
    T1C-2808
    T1C-2710
    T1C-2742
    T1C-2747
    T1C-2765
    T1C-2735
    T1C-2780
    T1C-2788
    T1C-2733
    T1C-2102
    T1C-2266
    T1C-2705
    T1C-2741

    Improvement

    Task

    Story

    Improvement

    Story

    Improvement

    T1C-2881
    T1C-2804
    T1C-2778
    T1C-2695

    Consent

    Introduction

    The Trust1Connector requires a user consent to function. This consent will be stored in the browsers localstorage for that user.

    The consent token is stored with a domain specific key;t1c-consent-{{applicationDomain}}::{{apiUrl}}

    When executing the consent flow, the user will be provided with a consent token which can be pasted into his clipboard. This token has to be passed with the Consent function which will perform a verfication (the token pasted in the clipboard - form the application context - should match with the token available on the clipboard for the T1C).

    The consent can be configured to have an expiration date, when this expiration date has been exceeded, a new consent will be asked towards the user.

    Consent dialog for implicit consent

    Upon installation of the Trust1Connector, a user will not be able to retrieve any data from the connector without first giving its consent, agreeing to give access to his/her card reader of filestorage. Without this consent, all requests will return a 401/404 Unauthorized response with error No valid consent found or at initialisation of the Trust1Connector SDK an error No valid consent found. The application should detect these errors and use it to trigger the consent dialog.

    The application shows this code word on screen and provide a button for 'copy-to-clipboard'. When the user has copied the code word to the clipboard (on user click button event), an implicit consent request can be executed towards the T1C. The T1C will grab the pasted code word from the user system clipboard and if both match, an implicit user consent has been granted for the calling application. The relation between the application and the local T1C instance is 'approved'. At this point the Trust1Connector returns a verified consent object that is stored in the browser's localstorage. This object is used to validate the consent and retrieve the necessary information for the Trust1Connector to function. This object will be re-used the next time the user wants to use the Trust1Connector until the consent expires.

    The clipboard value is a random value that is used to determine which agent you are running. This clipboard value needs to be pseudorandom so that we dont accidently find different agent.

    The Javascript has an exposed function that creates this value for you.

    The function is statically available on the T1CClient class and has the following interface.

    This will return the randomly generated value as a string value immediatley.

    To call this;

    Initially the concept was based on copying programmatically the code word, from the application context, to the user system clipboard. Although, through CAB forum, this not allowed; A user interaction is mandatory. The application should provide a 'copy-to-clipboard' button or alike in order to 'trigger' a user action. Once this action has been done, the T1C can be triggered to execute the consent.

    Currently, the need for a user interaction is a known limitation (aka. ). As this is the case, the W3C has a project ' ' to propose a solution for a new clipboard API in browsers. The use case for 'Remote clipboard synchronisation' as a use case included in this draft proposal. As this is a draft, and not yet supported by the browsers, we can not perform an automatic 'paste' ('copy' in terms of the browser) to the clipboard.

    Sending an implicit consent request can be done as follows:

    The code below is an example of a javascript event handler on a consent button.

    This call has 1 required and 2 optional parameters:

    1. Code Word (required): a code word in string format that will be shown in the consent dialog.

    2. Consent duration in days (optional): Allows the application the specify how long this consent is to be valid if granted. If not provided, the default value is 365 days.

    3. Callback function (optional): function to be called with the result of the consent request.

    The response of the consent will be an updated T1C Client which you after this point can use to continue your use-case(s).

    The response can also be a 400 Bad Request with status code 814501 "Invalid consent" or 814500 "No agents registered" which means that the request has been sent with the unique code but the Registry cannot not find the user associated with it by checking the clipboards of all connected users.

    This could mean that there is no T1C API client present or it is not running correctly.

    DNS Rebind

    How the Trust1Connector solves the DNS rebind issue

    The connector is using a DNS (depending on the connector partner), with a default value of:

    The given URL is registered with DNSSEC enabled, and resolves to a 'localhost' domain.

    Although the connector can run in a different mode (http, localhost, custom domain name, etc.), to solve the above issue, the following causes are probable:

    • DNS Rebind is enforced from your router or ISP (Internet Service Provider)

    Initialize Trust1Connector

    For initialisation of the T1C you need to prepare your application first by and importing them in such a way that you can call for the Javascript functions when you need them. When you've succesfully and installed the Trust1Connector you can initialize and use the Trust1Connector

    The Trust1Connector's architecture is created so that we can support a wide range of system setups. This means we can both support single users using the Trust1Connector but also systems where multiple users make use of the same hardware, we call this shared environments.

    Additionally to shared environments, we support remote desktops as an extension on shared environments.

    Since Trust1Connector version 3.6.1 we can provide integrators the support to initialise the Trust1Connector in different ways.

    Story

    The domain name is not whitelisted in your internal network

  • A local proxy is running and prevents the internal connector communication

  • An antivirus is blocking the connector communication

  • Your (custom) DNS server does not contain resolution for localhost and t1c.t1t.io

  • The functionality for automatic DNS Rebind resolutation solves the local connectivity issue by adding the DNS used by the connector to the host file of the device.

    As the connector is running in user-mode, and thus not have elevated rights, a separate process will be started on the operating system, asking the user to enter the `admin password` only with the purpose of adding the record to the host file of the system.

    When a user does not have `administrator` access to his device, and IT administrator can solve the issue (an apply it to all users from that domain).

    The following diagram show the logic begin the one-time check. The process runs on startup on a seperate system thread, and when executed succesfully, persists a marker file (.dnsrebind) in the installation directory of the connector.

    DNS Rebind logical flow

    Starting from from a clean installation, it will go trough the flow above and based on the outcome of the DNS resolving, the process will update the hostfile and create the markerfile

    The process will go trough the flow above and when successful, a DNS check is executed which a successful response.

    The process will go trough the flow above and when successful, the process will create the marker file without the need of updating the hostfile

    The process will go trough the flow above and when `failure`, the process will see the marker file, resulting in a error message that it could not resolve the domain. In this scenario, the markerfile indicates that the hostfile has been updated so the problem must be elsewhere.

    The process will go trough the flow above and when `failure`, the process will create the marker file and update the hostfile. When the final DNS check fails and it will return an error message.

    Here the markerfile also indicates that the hostfile has been updated so the problem must be elsewhere.

    DNS Rebind automatic resolution is implemented starting from v3.8.4, older version can solve this by following the troubleshooting guide: Connector Connection Issues

    Introduction

    https://t1c.t1t.io

    When installing the Trust1Connector in an owned system network, by default we ask to:

    • allow the outbound DNS for the Distribution Server

    • whitelist the local DNS used (t1c.t1t.io) on the router(s) or firewall(s)

    Logical Flow

    Process States

    Clean

    Success - marker present

    Success - no marker present

    Failure - marker present

    Failure - no marker present

    When the markerfile `.dnsrebind` is present in the connector directory, this means that the DNS entry has been added (or is already present) in the local host file.

    Adding the .dnsrebind file in the user folder, prevents the logic to be executed at service startup.

    Using this operation mode, the integrator can decide to use the Trust1Connector and inforce that no consent is needed. making it very straightforward for the end-user to utilise any functionality the Trust1Connector offers.

    In this mode we cannot support multiple instances of the Trust1Connector. Meaning shared environments and multiple users logged in on the same system can create unexpected behaviour.

    This is the default mode of operation and goes hand-in-hand with multi user instances. A consent is required to both request the user's permission to use the Trust1Connector on his system and also to correctly determine which instance of the Trust1Connector needs to be used.

    The Consent provides support to use the Trust1Connector with multiple users on the same system (even at the same time).

    Using Single Instance with consent as an operational mode, enforeces users to consent unregarded the environment - be it single device or multi user environment. Validity of the consent can be determined by the application.

    Just like the single instance with consent mode this mode requires a consent to both ask permission to the user and determine the correct instance of the Trust1Connector Agent/API.

    This mode support shared environments such as Citrix, terminal server and remote desktop.

    We will prepare the SDK's configuration Object, this object is used to pass information about which default port the Trust1Connector is running on, JWT key, API url, ... which is needed to properly contact and use the Trust1Connector.

    When the Trust1Connector is configured with a Distribution Service in mind you can provide a valid JWT token in the configuration object. You can retrieve such token via the Distribution Service based on the API key you received.

    Now we can create a complete Configuration Options object to be passed to the Trust1Connector.

    The T1C config options is a class that can be used to create a valid configuration object to initialize the Trust1Connector. Below you can find a class definition.

    t1cApiUrl: string Optional The URL that connects to the local Trust1Connector instances. This can be either localhost or a domain that directs towards localhost. By default this will be https://t1c.t1t.io

    t1cApiPort: string Optional The port defined to be used for the Trust1Connector. By default this is 51983

    t1cProxyUrl: string Optional - Deprecated The URL that connects to the local Trust1Connector Proxy instances. This can be either localhost or a domain that directs towards localhost. By default this will be https://t1c.t1t.io

    t1cProxyPort: string Optional - Deprecated The port defined to be used for the Trust1Connector Proxy. By default this is 51983

    jwt: string Optional The JWT token that is used to authenticate towards the Trust1Connector. This should be retrieved from the DS and is only needed when the Trust1Connector is configured to work with a DS and requires JWT validation

    applicationDomain: string Optional The domain of the application that is using the Trust1Connector. This is used to make sure the consent is only available for a specific web-application. This prevents various clients to interfere with eachother. This domain also tags the Distribution service transactions being sent to the Distribution service. This makes it easy to distinguish between applications/tags for the transactions

    When a remote DS is used you can set the following field with the correct DS url, this will in turn use the DS's capabilities of acting as a Trust1Connector proxy for enchanced security.

    Now we can continue to use the config variable to initialize and retrieve a T1CClient

    If you need to set up the Trust1Connector with a valid JWT token you can follow the documentation on the Authenticated Client page to retrieve a valid token from the DS.

    When you have a valid token you can provide this in the Configuration. This will make sure the Trust1Connector is usable until the token becomes unvalid. At which point you can refresh your token to continue to use the Trust1Connector. More information on how to retrieve,use and refresh a token can be found on the Authenticated Client page.

    Initialization of the Trust1Connector in many cases requires a user consent, the exception being when no registry is configured (either local or central) and if the Trust1Connector is run in a specific single modus enabled. More information can be found here. The registry allowed us to create a Trust1Connector that works in any environment, without the need for Administrative rights from the users, wether it be Standalone, Multi session, RDP, Citrix, ...

    To Initialize the Trust1Connector a Consent is required(when a central or local registry is present) or when the modus is set to optional consent. When no consent can be found the error codes 814500 or 814501 will be thrown. This means that either the previous consent is not valid anymore or no consent was given yet.

    More information regarding the consent can be found on the Consent page which explains it in more detail.

    If you have the optional consent mode enabled the consent error will not appear but will either give a valid Client to use or a 112999 error, depicting it could not find any active instance of the Trust1Connector.

    When either no consent is present or its invalid you will receive a invalid client object (line 8 in example above) that can be used to trigger the getImplicitConsent function in the Core serivce.

    The Consent requires a user action to copy some data to its clipboard. This data is used by the T1C registry to make sure you're targetting the correct instance of the Trust1Connector. More information about this can be found here.

    The signature of the getImplicitConsent function is as follows;

    This function expects:

    codeword: string The string value that is saved to the user's clipboard needs to be sent to the Consent function.

    durationInDays: number Optional Amount of days that the consent is valid.

    callback: (error?: T1CLibException, data?: T1CClient) Optional Callback when you're not using ES

    Below is a small javascript example of how you can trigger the getImplicitConsent function

    After this you will have a client that can be used to execute the rest of the functionality that the Trust1Connector has to offer.

    When your instance of the Trust1Connector has the optional consent mode enabled but still want to enforce the consent flow you can use the following explicit consent initialisation.

    This will ignore the enabled feature of having the consent being optional and will require a valid consent to operate the Trust1Connector.

    To provide a consent, we suggest you use the clipboard functionality available in browsers. The most supported way is via document.exeCommand and below you can find an example of this.

    There is also a clipboard API but this is not fully supported yet

    GET https://ds.t1t.io/v3_5/tokens/application

    This endpoint will return a valid JWT token to use for a certain period based on the API-key you provide in the `apikey` header

    Name
    Type
    Description

    apikey

    string

    API-key received from Trust1Team

    {
        "success": true,
        "data": "eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0...v8_Mg2PfdhCMQ"
    }
    {
        "message": "No API key found in request"
    }
    {
        "success": false,
        "description": "Invalid API key",
        "code": 1005,
    }

    The Trust1Connector has a Develop, Acceptance and production version. The difference between them is mainly the Distirbution service connection and the port number they use.

    The port numbers of the Trust1Connector are;

    Environment
    Port number
    Distribution service

    Production

    51983

    https://ds.t1t.io

    Acceptance

    Introduction

    Mode of operations

    Single Instance Without Consent

    Please contact support if you need support for this modus. As this is not the default mode and requires the Trust1Connector to be run in a specific context

    adding the SDK JS files to your project
    downloaded
    class T1CConfigOptions {
      constructor(
        public t1cApiUrl?: string,
        public t1cApiPort?: string,
        public t1cProxyUrl?: string, // deprecated
        public t1cProxyPort?: string, // deprecated
        public jwt?: string,
        public applicationDomain?: string, // "rmc.t1t.be"
      ) {}
    }
    // ...
    
    let environment = {
        t1cApiUrl: 'https://t1c.t1t.io',
        t1cApiPort: '51983',
        t1cProxyUrl: 'https://t1c.t1t.io',
        t1cProxyPort: '51983',
        jwt: 'eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0..._Mg2PfdhCMQ',
        applicationDomain: 'test-app'
    };
    
    const configoptions = new T1CSdk.T1CConfigOptions(
            environment.t1cApiUrl,
            environment.t1cApiPort,
            environment.t1cProxyUrl,
            environment.t1cProxyPort,
            environment.jwt,
            environment.applicationDomain
        );
    config = new T1CSdk.T1CConfig(configoptions);
    
    // ...
    // When remote DS is used set the following parameter
    config.dsUrl = "https://acc-ds.t1t.io";
    // ...
    
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        console.log("Client config: ", client.localConfig);
        core = client.core();
        core.version().then(versionResult => console.log("T1C running on core "+ versionResult));
    }, err => {
        if (err.code == 814500 || err.code == 814501) {
            client = err.client;
            // (new) Consent is required
        }
        else if(err.code == 112999) {
            // Could not connect with the Trust1Connector
        } else {
            // an uncatched error occured
            console.error("T1C error:", err)
        }
    });
    
    // ...
    public getImplicitConsent(codeWord: string, durationInDays?: number, 
        callback?: (error?: T1CLibException, data?: T1CClient) => void
    ): Promise<T1CClient>
    client.core().getImplicitConsent(document.querySelector(".clipboard-data").innerHTML).then(res => {
        console.log("Consent Executed")
        client = res;        
        // Use the client for your use-cases
    }, err => {
        // Failed, use the error client to retry the consent
        this.client = err.client;
        console.error(err.description ? err.description : err)
    })
    // Global client to be used over the entire application
    const client = null
    
    // Prepare the configuration
    let environment = {
        t1cApiUrl: 'https://t1c.t1t.io',
        t1cApiPort: '51983',
        t1cProxyUrl: 'https://t1c.t1t.io',
        t1cProxyPort: '51983',
        jwt: 'eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0..._Mg2PfdhCMQ',
        applicationDomain: 'test-app'
    };
    
    const configoptions = new T1CSdk.T1CConfigOptions(
            environment.t1cApiUrl,
            environment.t1cApiPort,
            environment.t1cProxyUrl,
            environment.t1cProxyPort,
            environment.jwt,
            environment.applicationDomain
        );
    config = new T1CSdk.T1CConfig(configoptions);
    
    // Initialize the Trust1Connector with the previously created configuration object
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        console.log("Client config: ", client.localConfig);
        core = client.core();
        core.version().then(versionResult => console.log("T1C running on core "+ versionResult));
    }, err => {
        if (err.code == 814500 || err.code == 814501) {
            // (new) Consent is required
        }
        else if(err.code == 112999) {
            // Could not connect with the Trust1Connector
        } else {
            // an uncatched error occured
            console.error("T1C error:", err)
        }
    });
        
        
    
    // when the user has clicked on the clipboard/consent button we execute the getImplicitConsent function
    document.querySelector(".clipboard").addEventListener("click", (ev) => {
        if (client != null) {
            client.core().getImplicitConsent(document.querySelector(".clipboard-data").innerHTML).then(res => {
                console.log("Consent Executed")
                client = res;        
                // Use the client for your use-cases
            }, err => {
                this.client = err.client;
                console.error(err.description ? err.description : err)
            })
        }
    
    })
    // ...
    
    T1CSdk.T1CClient.initializeExplicitConsent(config).then(res => {
        client = res;
        console.log("Client config: ", client.localConfig);
        core = client.core();
        core.version().then(versionResult => console.log("T1C running on core "+ versionResult));
    }, err => {
        if (err.code == 814500 || err.code == 814501) {
            client = err.client;
            // (new) Consent is required
        }
        else if(err.code == 112999) {
            // Could not connect with the Trust1Connector
        } else {
            // an uncatched error occured
            console.error("T1C error:", err)
        }
    });
    
    // ...
    const tokenNode = document.querySelector('.consent-token');
    var range = document.createRange();
    range.selectNode(tokenNode);
    window.getSelection().addRange(range);
    try {
        // Now that we've selected the anchor text, execute the copy command
        document.execCommand('copy');
    } catch(err) {
        console.log('Oops, unable to copy');
    }
    
    // Remove the selections - NOTE: Should use
    // removeRange(range) when it is supported
    window.getSelection().removeRange(range);
    const clipboardData = tokenNode.textContent;

    Single Instance With Consent

    Multi-user Instance With Consent

    Creating the configuration object

    Retrieving JWT tokens should be handled in your own backend to maximize security

    T1CConfigOptions

    t1cProxyUrl and t1cProxyPort are deprecated since 3.5.x and only used in 3.4.x versions.

    Parameters

    Authenticated client

    Initializing the Trust1Connector SDK

    Full example

    Enforcing consent flow in a optional consent enabled Trust1Connector

    Clipboard

    The code below is an example of how you can integrate a copy command in the webbrowser

    Retrieve JWT token

    Headers

    Trust1Connector environments

    These port numbers are linked to the Trust1Connector distributed by Trust1Team. If you have a custom installation these will be different. Please contact your distributor for more information.

    public static generateConsentToken(): string
    # regular imported javascript via script tag
    T1CSdk.T1CClient.generateConsentToken()
    # Import loaded via NPM
    import {T1CClient} from "t1c-sdk-js";
    
    T1CClient.generateConsentToken()
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        console.log("Client config: ", client.localConfig)
        core = client.core();
    }, err => {   
         if(err.code == 814501 || err.code == 814500) {
            console.log(err)
            client = err.client
            $('#consentModal').modal('show', {
                keyboard: false
            });
            $('.consent-token').text(client.core().generateConsentToken());
        } else if (err.code == 112999) {
            // Unavailable
        } else {
            console.error("T1C error:", err)
        }
    }); 
    $('#consentModal .btn-primary').on('click', (ev) => {
        const tokenNode = document.querySelector('.consent-token');
        var range = document.createRange();
        range.selectNode(tokenNode);
        window.getSelection().addRange(range);
        try {
            document.execCommand('copy');
        } catch (err) {
            console.log('Oops, unable to copy');
        }
        window.getSelection().removeRange(range);
        const clipboardData = tokenNode.textContent;
        const validityInDays = 365
        
        client.core().getImplicitConsent(clipboardData, validityInDays).then(consentRes => {
            client = consentRes // replace the client and other set variables of the T1C
            core = client.core();
            core.version().then(versionResult => console.log("T1C running on core " + versionResult));
            $('#consentModal').modal('hide');
        }, err => {
            console.error(err)
        })
    });

    Generating a random clipboard value

    If you decide not to use this function, the value needs to be prefixed with `::t1c::miksa::

    User clipboard remark

    clipboard.js
    Clipboard APIs

    Token typing models

    This page describes all generic token models used.

    Generic token

    The Generic token interface is an interface used to integrate all supported tokens. This interface relies on the fact that you will need to provide a valid module. The module suggested from the reader response can be used here.

    All model information can be found in the

    Initialise a Trust1Connector client with a valid configuration:

    In order to get all connected card-readers, with available cards:

    This function call returns:

    As you can see in the response we get a property suggestedModule which is returned based on the card, reader and AID information. This suggested module can be used in the generic interface.

    51883

    https://acc-ds.t1t.io

    Develop

    51783

    None

    allow or whitelist the local DNS in anti-virus agents

    Typically when one of the above apply, and is not executed, the connector will run, but may not be reachable.

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Models

    Using the generic interface can be done as follows;

    The pin and pinType are optional and are used for unlocking the pace layer (if the card is protected with a pace layer).

    At this point for each use-case you will need to provide the module. This can be manually defined or be retrieved from the suggestedModule property in the reader-response. In the examples below we provide the module as a variable module

    The card holder is the person identified using the Belgian eID card. It's important to note that all data must be validated in your backend. Data validation can be done using the appropriate certificate (public key).

    Contains all card holder related data, excluding the card holder address and photo. The service can be called:

    An example callback:

    Response:

    Contains the card holder's address. The service can be called:

    Response:

    Contains the card holder's picture stored on the smart card. The service can be called:

    Response:

    The token info contains generic information about the card and it's capabilities. This information includes the serial number, file types for object directory files, algorithms implemented on the card, etc.

    Response

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'citizen CA certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not. The service can be called:

    Response:

    You can also fetch the root certificate via the function rootCertificateExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    The response looks like:

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    You can also fetch the root certificate via the function authenticationCertificateExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    The response looks like:

    Contains the citizen certificate stored on the smart card. The 'citizen certificate' is used to sign the 'authentication certificate' and the 'non-repudiation certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    You can also fetch the root certificate via the function intermediateCertificateExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    The response looks like:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    The response looks like:

    You can also fetch the root certificate via the function nonRepudiationCertificateExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    You can also fetch the root certificate via the function encryptionCertificateExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    The response looks like:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    You can also fetch the root certificate via the function allCertsExtended this has the capabilities to return multiple certificates if the token has multiple of this type.

    The response looks like:

    All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the biometric data

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    Data can be signed using the Belgian eID smart card. To do so, the T1C-GCL facilitates in:

    • Retrieving the certificate chain (citizen-certificate, root-certificate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Interface

    Models

    Initialise the Trust1Connector JS

    Obtain the Reader information

    Token typings model page

    Cardholder Information

    Biometric data

    Address

    Picture

    Token info

    Certificates

    Extended certificates

    Root Certificate

    Authentication Certificate

    Intermediate Certificate (citizen)

    Non-repudiation Certificate

    Encryption Certificate (RRN)

    All certificates

    Data Filter

    Filter Card Holder Data

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    export class ModuleDescriptionResponse extends DataObjectResponse {
      constructor(public data: TokenModuleDescription, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenCertificateResponse extends T1CResponse {
      constructor(public data: TokenCertificate, public success: boolean) {
        super(success, data);
      }
    }
    
    
    export class TokenCertificate {
      constructor(
          public certificate?: string,
          public certificates?: Array<string>,
          public certificateType?: string,
          public id?: string,
          public parsedCertificate?: Certificate,
          public parsedCertificates?: Array<Certificate>
      ) {}
    }
    
    export class TokenAddressResponse extends DataObjectResponse {
      constructor(public data: TokenAddressData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenPictureResponse extends DataObjectResponse {
      constructor(public data: TokenPictureData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenVerifyPinResponse extends DataObjectResponse {
      constructor(public data: TokenVerifyPinResponseData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenVerifyPinResponseData {
      constructor(
          public verified: boolean
      ) {}
    }
    
    export class TokenSignResponse extends DataObjectResponse {
      constructor(public data: TokenSignResponseData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenSignResponseData {
      constructor(
          public data?: string
      ) {}
    }
    
    export class TokenAuthenticateResponse extends DataObjectResponse {
      constructor(public data: TokenAuthenticateResponseData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenAuthenticateResponseData {
      constructor(
          public data?: string
      ) {}
    }
    
    export class TokenModuleDescription {
      constructor(
          public desc: string
      ) {}
    }
    
    export class TokenAddressData {
      constructor(
        public municipality?: string,
        public rawData?: string,
        public signature?: string,
        public streetAndNumber?: string,
        public version?: number,
        public zipcode?: string
      ) {}
    }
    
    
    
    export class TokenAllDataResponse extends DataObjectResponse {
      constructor(public data: TokenAllData, public success: boolean) {
        super(data, success);
      }
    }
    
    
    export class TokenAllData {
      constructor(
        public picture?: TokenPictureData,
        public biometric?: TokenBiometricData,
        public address?: TokenAddressData,
      ) {}
    }
    
    export class TokenPictureData {
      constructor(
          public picture?: string,
          public signature?: string,
          public width?: number,
          public height?: number,
      ) {}
    }
    
    export class TokenData {
      constructor(
          public rawData?: string,
          public version?: string,
          public serialNumber?: string,
          public label?: string,
          public prnGeneration?: string,
          public eidCompliant?: string,
          public graphicalPersoVersion?: string,
          public versionRfu?: string,
          public electricalPersoVersion?: string,
          public electricalPersoInterfaceVersion?: string,
          public changeCounter?: number,
          public activated?: string,
      ) {}
    }
    
    export class TokenDataResponse extends DataObjectResponse {
      constructor(public data: TokenData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenBiometricData {
      constructor(
        public birthDate?: string,
        public birthLocation?: string,
        public cardDeliveryMunicipality?: string,
        public cardNumber?: string,
        public cardValidityDateBegin?: string,
        public cardValidityDateEnd?: string,
        public chipNumber?: string,
        public documentType?: string,
        public firstNames?: string,
        public name?: string,
        public nationalNumber?: string,
        public nationality?: string,
        public nobleCondition?: string,
        public pictureHash?: string,
        public rawData?: string,
        public sex?: string,
        public signature?: string,
        public specialStatus?: string,
        public thirdName?: string,
        public version?: number,
        public issuer?: string
      ) {}
    }
    
    export class TokenBiometricDataResponse extends DataObjectResponse {
      constructor(public data: TokenBiometricData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class TokenAlgorithmReferencesResponse {
      constructor(public data: TokenAlgorithmReferences, public success: boolean) {
      }
    }
    
    export class TokenAlgorithmReferences {
      constructor(public ref: Array<string>) {
      }
    }
    
    export class TokenResetPinResponse {
      constructor(public data: TokenResetPin, public success: boolean) {
      }
    }
    
    export class TokenResetPin {
      constructor(public verified: boolean) {
      }
    }
    
    
    export class PinType {
      static PIN = 'Pin';
      static CAN = 'Can';
    }
    
    
    // Requests
    export class TokenAuthenticateOrSignData {
        constructor(public algorithm: string, public data: string, public pin?: string, public pace?: string, public id?: string, public osDialog?: boolean, public txId?: string, public language?: string, public base64Encoded?: boolean, public timeout?: number) {
        }
    }
    
    export class TokenVerifyPinData {
        constructor(public pin?: string, public pace?: string, public osDialog?: boolean, public base64Encoded?: boolean, public timeout?: number) {
        }
    }
    
    export enum TokenResetPinReferenceType {
        issign = "issign",
        isauthenticate = "isauthenticate",
        isencrypt = "isencrypt"
    }
    
    export class TokenResetPinData {
        constructor(
            public puk: string,
            public pin?: string,
            public resetOnly?: boolean,
            public osDialog?: boolean,
            public reference?: TokenResetPinReferenceType,
            public base64Encoded?: boolean) {
        }
    }
    
    export class PaymentVerifyPinData {
        constructor(public pin?: string, public osDialog? :boolean, public base64Encoded?: boolean, public timeout?: number) {
        }
    }
    
    export class PaymentSignData {
        constructor(public txId: string, public language: string, public data: string, public timeout?: number) {
        }
    }
    
    
    export class TokenCertificateExtendedResponse extends T1CResponse {
      constructor(public data: TokenCertificateExtended, public success: boolean) {
        super(success, data);
      }
    }
    
    
    export class TokenCertificateExtended {
      constructor(
        public certificates?: Array<T1CCertificate>
      ) {
      }
    }
    
    
    export class T1CCertificate {
      constructor(
        public certificate?: string,
        public certificateType?: string,
        public id?: string,
        public subject?: string,
        public issuer?: string,
        public serialNumber?: string,
        public url?: string,
        public hashSubPubKey?: string,
        public hashIssPubKey?: string,
        public exponent?: string,
        public remainder?: string,
        public parsedCertificate?: Certificate
      ) {
      }
    }
    
    export class TokenVersionResponse extends T1CResponse {
      // use union type to be backwards compatible with versions before 3.6.0
      constructor(
        public data: TokenVersion,
        public success: boolean,
        public signature?: string
      ) {
        super(success, data, signature);
      }
    }
    
    export class TokenVersion {
      constructor(
        version: string,
      ) {}
    }
    export interface AbstractEidGeneric {
      allData(module: string, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
      allCerts(module: string, parseCerts?: boolean,  filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      biometric(module: string, callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
      tokenData(module: string, callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
      address(module: string, callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
      picture(module: string, callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
      rootCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      intermediateCertificates(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      encryptionCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      issuerCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(module: string, parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      intermediateCertificatesExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      encryptionCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      issuerCertificateExtended(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(module: string, body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(module: string, body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(module: string, body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      signRaw(module: string, body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(module: string, callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(module: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": ["Belgian eID Card"]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false,
          "suggestedModule": "beid"
        }
      ],
      "success": true
    }
    var generic = client.generic(selected_reader.id, pin, pinType);
    generic.biometric(module, options, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "birthDate": "15 JUL  1993",
     "birthLocation": "Roeselare",
     "cardDeliveryMunicipality": "Avelgem",
     "cardNumber": "592..8233",
     "cardValidityDateBegin": "27.05.2015",
     "cardValidityDateEnd": "27.05.2025",
     "chipNumber": "U0xHk...EstwAjEpJQQg==",
     "documentType": "01",
     "firstNames": "Gilles Frans",
     "name": "Platteeuw",
     "nationalNumber": "930...154",
     "nationality": "Belg",
     "nobleCondition": "",
     "pictureHash": "Fqva9YCp...JKyn8=",
     "rawData": "AQw1OTIxMjQwNTgy...TARFBar2vWAqTW+axEIuyskBgFySsp/",
     "sex": "M",
     "signature": "hKys9WMjUm4ipg...14xUCg/98Y9/gP/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
     "specialStatus": "0",
     "thirdName": "J",
     "version": "0"
    }
    generic.address(module, callback);
    {
     "municipality": "Hoeselt",
     "rawData": "ARJLZXJrc...AAAAAA==",
     "signature": "mhPyeRg25H...w==",
     "streetAndNumber": "Kerkstraat X",
     "version": "0",
     "zipcode": "3730"
    }
    generic.picture(module, callback);
    {
      "data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
      "success": true
    }
    {
      "data": {
        "eid_compliant":48,
        "electrical_perso_interface_version":0,
        "electrical_perso_version":3,
        "graphical_perso_version":7,
        "label":"BELPIC",
        "prn_generation":4,
        "raw_data":"MCcCAQAEEFNMSU4z...JFTFBJQwMCBDCeBAcDAAA=",
        "serial_number":"534C494E..1231C",
        "version":0,
        "version_rfu":0
        },
        "success": true
    }
    allCertsExtended(module: string, parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    rootCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    intermediateCertificatesExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    authenticationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerCertificateExtended(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "intermediateCertificates": {
                "certificates": [...]
            },
            "encryptionCertificate": {
                "certificates": [...]
            }
       }
    }
    generic.rootCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    {
        "success" : true
        "data" : {
            "certificates": [
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            ]
        }
    }
    generic.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    {
        "success" : true
        "data" : {
            "certificates": [
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            ]
        }
    }
    generic.intermediateCertificates(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    {
        "success" : true
        "data" : {
            "certificates": [
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            ]
        }
    }
    generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    {
        "success" : true
        "data" : {
            "certificates": [
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            ]
        }
    }
    generic.encryptionCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    {
        "success" : true
        "data" : {
            "certificates": [
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            ]
        }
    }
    generic.allCerts(module, parseCertsBoolean, callback);
    {
     "rootCertificate": {
     ...
     },
     "authenticationCertificate": {
     ...
     },
     "nonRepudiationCertificate": {
     ...
     },
     "intermediateCertificates": {
     ...
     },
     "encryptionCertificate": {
     ...
     }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "intermediateCertificates": {
                "certificates": [...]
            },
            "encryptionCertificate": {
                "certificates": [...]
            }
       }
    }
    var filter = [];
    generic.allData(module, { filters: filter}, callback);
    {
     "picture": {
      "picture": "/9j/4AAQSkZJRgABAgEBLAEsAAD/.../wAALCADIAIwBAREA/8QA0gAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoLEAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/2gAIAQEAAD8A9JpKKWiikooooopaKSilooooopKr3d9bWaFriVEwM4J5Ncjq3jUxkixQADozjJNcze+L9WndWF20OOCI/lzRb+KtYjhIN67Z7vyf1qT/AIS3Wc5F2OnQgY/lWrovjC7hYLqJ86IkksPvCustPEumXbbUuAjYzh+K1UkWRA6MGU9CDkGn0UUUUUUUhOBk8CuY1zxOls/kWjbnH3pAMgewrz7VtWmu7gvJIzZ65NZk1wSBjOagWbn5lB+vagy7+2KlilUE7eRj1qS3ncSEE4X3qwzNs81Dgg9K19G8VXumTLFv8yDOWjb+len6bqMGp2qz2zZU8Ed1PpVyiiiiio5pkgiaSRgqKMkmuH8ReKXlMlpAAkHRnB5b29q4+e5HzAHjPFZkoLyhevH6014XUcjBqAow5xQEYjFPClDxkCnq20AkZ/xqyl2oUK4xu6n0qwgguZQ28K2Ofc1v6Pqs2lSRGJzsLAOv94d69MtriO6gSaFgyMMg1LS0UUlcn491FbfS/sicyzEH6AGvOCzuApPOakt7CWYk7TjNXE0iUNnyyfpVqPQ53XiNwPepYfDMhb94GAq5/wAIzbhc4IPpVK/8OYjzEMmsWbRZ0XIUnHtVRrR4/vqR9RSwQGXdt4Zav2rbFww6DI5ruvBuqIIjaSuMu2Y8/TpXYUtFFIa8r8W6h9v1d9mCqHYuO4FVdM0t7iZWb8a6y10+KNQCOlXFijQfKop6g9hUmw4pjoRzmopEyvIqrJEjDGKpXGnwzoQ68+1YNxpv2Ry8RPHrVGUqse4MN38Qq7o8o8kOh+dG3AjsRXpejapHqVsDkLMo+dM8/WtOiis/WrxrHTJp1GWAwOeme9eWqqzTln6k5rqNLhWKFcDmtJRk1aSPPWp0i21J5dRSx8VWKVXkQA1WmwvGDzWVegSRsp4zXNT2WwMASSxqa1kNimMBkOB9fWt7QLx4ddgaNCyyLtIHevR6Wiuf8ZsRobAdWcD+dcLYQZlHck/lXWQKEjUVZj69OlXI+manXnvTiADioXPJ4qBhVaQ/NVWbkZ7VlXeDmqRYY27Rn1rOmkDXOwKBgH8av6XOba9guVz8hA2+1epg5GaWiuf8ZqTom4fwyKf5iuS0uFiQcV0MYwgBqxH1FWl6VLGeKcxOOaaRmoZAcVTkBqrOcL61j3B5NVgducVXkeOOXLKMt1p9tIsyjaAMGvVI+I1+gp9FZXiOAT6LcKRnaN35Vy+lhfKJ9Kv+cifeYACpIry3A5kA+tW1uYmXKuD+NSRzDseKl3gjrTS47UhYAGqFxINxqhcSA8ZrPlQmq8kZArNujljkdBUuhAy3cUOOWdRXrY4FLRUN0iSW8iSkBGUg5riLGMrbzxq3IkI3CozpuWZmnkye+6qT6TlmPnkk9M1Smsbq3OUuOOvWtDTrq4j+V5CRn1rpIZy6ZNSbiBz1qneXphFcpqmqzyNiJiBnqKyl+33DDZJL9dxq2i6pDg7mYehNX7a/lx5d5EADwGHUVBeR/MfT2q/4It2n10vtykY3H29K9MpaSsLxKJJo4oI5Ci53NjvWbbweUGAH3sE5qG8DpnqB7CsKNru7umitUKgdXbqay3m1L7cluxlMm/DAqMYrqLfTW5DKAw7joa1LRCnDVNelYo91cXq13NcMfLDbAcA+tVbXTppyzMrNtGSq9RTP7VhgZY44HBP+1k1Zi1LzZNgbOexGCKS8kwQcc1LM4ayeT0Sl8M+IhpDzfuA4kwCe+BXqFldxXtrHcQnKOMjNWKSsfV48zI3qMVVwpIA5xxTpI1bqBVNrRQ25EwfVaja3cybtgz/eK81ahjKrz1pTwR6k1U1aQ/Zm57VhQKDGhAyBWxatHACUXbuHOO9Yt3plol01wkWSTnGazLixaW5EsSbSO4q5HZu6Ey9R0qLUQYNOcdA3FY1vGS4wK9f8NQtBolurdSC2PrWtRWfqoHlI3cHFZUXJJ9TU3U4xxTguKdsyM1FINtQNjcKpauC1uwHORWLYsAAhPStqOPKAjoaHhU8Fc1G0KDouKgmUBTisDXCTBGoxgtk1W02AysoUclgK9it4hDBHGOiKFqWiqWppvtT7EGsgKoGVJB7ip161KoWlY4qrctjGOpqCJd74JqLUlVYic8YrlI22ySSKehzXUWDCa2RxzkVaaMVUnXaDWXdzBVIzziuf1Pc80MS9x1rd8Maa39qxRucqhDtj2r0elopkiCRGRuhGKxJreaFipQlB/EBTA2Dih5tg4ySeAKlUnbufr6VBOpkBA4PassR3NtIZJJ/MB/h24xWDr+rySYihU+/NZULXMkXlrHyepFdfoYaG1RG5IFa7yZTIrNv5gqHmudnn3zgdeazrjL3+7PyggV6J4QgY28ly643YRT64610tFFJTXXcjL6jFc+/BIP8ACcUKoEm888YFI13GuVkbafehZ4uu8UOYpVwGGazp9KtmYs2AfempZQx524pyusRAyKkEuXU9jxWNrUxUsnc1k26F50U9WIFd1F4N08XCzu0rdCUJ4Jro0RY0VEUKqjAA7U+iiikrCvV2Xki9ic1BExDYPOKL6xhvIdrqM9j6VjmwNuNiu6/8CzUiW0uw73bOOCADVO7hulGRIxY9iOKy5RfgnbKB+NLZWWp3EwMtwBHnPU8106xrFGiZzt5JNcpqdyLnVWVOUU81a0GL7TrdsmMgOCfoDmvUaWiiiikrM1aHlJh0HBrNBAcZqcnH0qJ1EnBGaqvGy/dPFU51mfv+tVRaNnLc/Wp0cRLgHmqup35hs2AJ8xxgYrBijKRlm+8eSa6nwLbbryW4b+EYFd5RRRRRRVXURmxlz7fzrmDJ820noavoQ0WCcmlQZpXjBGarMijpzVedBtJNZczbSTmsW6k864BY/Kvaomk3sFB4rtfBO398F6BcV19FFFFFFVr/AJs5fpXLXEJK716imWt5tOxzir6Tqe9JLcAcbhUTTrt4Iqhc3IOQGrA1C/CcZ56VkPOzHr1p0JZ32r07mu/8ELsaYZ5K5rsKKKKSloqtfnFnL9KwkAP41Qv7I53R9ax5ri5tzhg31qm+qzdDzUb6zKBjAqlNqkrZxwTWe8jSOSSSalhiaRgO1a1tAsYA711/hA7bpx6qa7CikpaSio1njZioYZHWs/UdQtmhlgjnjeUYyinJHPes2M5HNPYDbiqr28cvyuoIqjceH7eQ5AI+lZ0vhyME4Z/zqjPoiRZ5aqBslRulXbe3woOKtLGc8itvQJxbXqseh4NdRPqaxpujjMnqAcYHrToNShlAz8h96mkvLeJQ0k8aKe7MBT0uIZF3JNGy+qsCKqajfx2gUFvmJ6ZrB1HxUkSttIGOOtcpfeK5jC8dsxDP1f0+laehxeVp8cjcyTfOxPU1uRmpm6VAchqkEmKjkcYz0rJvGDZrJMe+Tgd6vRwbU6UpTBqS1O2ZT71vRkSJtakaARITyy+3UVyXiXUTvijEqugB+6en1rJi1AqmN7D6Gut8S61a6XKipbieSRSSXPSuBv8AUZbyQlwFXP3VGAKp7q9B0OTzdLtG/wBnH5VtR1Z6ionXnIprDI6VWkjB/i5qnPCMHAqCCAeZyKutGoWqsvBqOM4cH3rcgOQKvRNxisbxB4ettQgaZcRToM7gOv1rgEvzAvl+VE+D1K1//9k="
     },
     "biometric": {
      "birthDate": "15 JUL  1993",
      "birthLocation": "Roeselare",
      "cardDeliveryMunicipality": "Avelgem",
      "cardNumber": "592124058233",
      "cardValidityDateBegin": "27.05.2015",
      "cardValidityDateEnd": "27.05.2025",
      "chipNumber": "...==",
      "documentType": "01",
      "firstNames": "Gilles Frans",
      "name": "Platteeuw",
      "nationalNumber": "...",
      "nationality": "Belg",
      "nobleCondition": "",
      "pictureHash": "...=",
      "rawData": "...+axEIuyskBgFySsp/",
      "sex": "M",
      "signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
      "specialStatus": "0",
      "thirdName": "J",
      "version": "0"
     },
     "address": {
      "municipality": "Hoeselt",
      "rawData": "...==",
      "signature": "...+Evety1PnTE4pqXaHgBxIpk+P8kRL5W3zDV+../../..+YoHBC9KqTmSpl5KULxdnKiyCt+2RyJdzE2wyoymjRmysIhJy1wW9PRnx99S1TFqQLuc0tyBmkBPR4aFqmOq4a7zqd0q2Q1g+BbnwJ4d3oa10ia5+0kBXf0THoXv3HYIHlnwhBMfAtWzPnFrYBuAKTwyl7yBF5IFfXFpGWuVZUTJElgNcmNvsHMnAhVwDw==",
      "streetAndNumber": "Kerkstraat X",
      "version": "0",
      "zipcode": "3730"
     }
    }
    var filter = ['biometric'];
    generic.allData(module, { filters: filter }, callback);
    {
     "biometric": {
      "birthDate": "15 JUL  1993",
      "birthLocation": "Roeselare",
      "cardDeliveryMunicipality": "Avelgem",
      "cardNumber": "592124058233",
      "cardValidityDateBegin": "27.05.2015",
      "cardValidityDateEnd": "27.05.2025",
      "chipNumber": "...==",
      "documentType": "01",
      "firstNames": "Gilles Frans",
      "name": "Platteeuw",
      "nationalNumber": "...",
      "nationality": "Belg",
      "nobleCondition": "",
      "pictureHash": "...=",
      "rawData": "...+axEIuyskBgFySsp/",
      "sex": "M",
      "signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
      "specialStatus": "0",
      "thirdName": "J",
      "version": "0"
     }
    }
    var filter = [];
    generic.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
     ...
     },
     "authenticationCertificate": {
     ...
     },
     "nonRepudiationCertificate": {
     ...
     },
     "intermediateCertificates": {
     ...
     },
     "encryptionCertificate": {
     ...
     }
    }
    var filter = ['rootCertificate'];
    generic.allCerts(module, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     }
    }
    var filter = null;
    generic.allCerts(module, { filters: filter}, callback);
    {
     "rootCertificate": {
     ...
     },
     "authenticationCertificate": {
     ...
     },
     "nonRepudiationCertificate": {
     ...
     },
     "intermediateCertificates": {
     ...
     },
     "encryptionCertificate": {
     ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true
    }
    generic.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false
    }
    generic.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    generic.signRaw(module, data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = true;
    generic.sign(module, data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    generic.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    generic.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {}
    generic.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    generic.authenticate(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    generic.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    

    Aventra MyEID PKI

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Aventra MyEID PKI Card is a cryptographic smart card conforming to common Public Key Infrastructure standards like ISO/IEC-7816 and PKCS#15v1.0 specification. It can be used for various tasks requiring strong cryptography, e. g. logging securely to Windows, encrypting e-mail, authentication, and electronic signatures. The card is also available as a Dual Interface version, compatible with T=CL protocol and also emulating Mifare™. The card is a JavaCard with Aventra MyEID applet that implements the functionality.

    The applet implements the FINEID S1 v1.12 specification and it can be configured to include all or any subset of the features specified in FINEID S4-1 or S4-2 specifications. Starting from version 2.2.0 the applet supports both 1024 and 2048 bit RSA keys. From version 3.0.0 (MyEID3) the applet supports keys from 512 bit up to 2048 bit in increments of 64 bits. The applet is fully compatible with JavaCard 2.1.1 and GlobalPlatform 2.0.1 specifications. The new MyEID version 3 (MyEID3) is now released and it uses the new JavaCard 2.2.1 and GlobalPlatform 2.1.1 platform. The new MyEID3 now supports RSA keys from 512 up to 2048 bits in 64 bit increments. MyEID3 supports file sizes up to 32767 bytes and 14 different PIN-codes can be created and used. The number of RSA keys is only limited by the available memory and maximum numbers of files (see PUT DATA: INITIALISE APPLET).

    References

    The most relevant specifications and standards are:

    • ISO/IEC 7816-4

    • ISO/IEC 7816-8

    • ISO/IEC 7816-9

    • JavaCard 2.1.1, MyEID3: 2.2.1

    This document describes the functionality provided by the Aventra smartcard - which is a PKI container - on the T1C-GCL (Generic Connector Library) implemented version:

    • MyEID - reference manual v1.7.36

    All model information can be found in the

    When initialisation is finished you can continue using the aventra object to execute the functions below.

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    The expected response for this call should be;

    The expected response for this call should be;

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Exposes all the certificates publicly available on the smart card. The following certificates can be found on the card:

    • Root certificate

    • Signing certificate

    • Authentication certificate

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    The expected response for this call should be;

    This will return information of the Aventra card.

    The expected response for this call should be;

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Contains the 'root certificate' stored on the smart card.

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and signing.

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key.

    The expected response for these calls should be in the following format;

    The expected response for these calls should be in the following format;

    To sign data, an algorithm must be specified in the algorithm property (see ), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.

    Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The expected response for this call should be;

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    The expected response for this call should be;

    The expected response for this call should be;

    The expected response for this call should be;

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

  • GlobalPlatform 2.0.1 ' (Open Platform), MyEID3: GlobalPlatform 2.1.1

  • FINEID S1 and S4 documentation

  • Issuer certificate
  • Encryption certificate

  • Interface

    Models

    Examples

    Create the Aventra module

    Token info

    All certificate filters

    all Key references

    all Certificates

    Extended certificates

    Token data

    Certificate

    Root certificate

    Authentication certificate

    Non repudiation certificate

    Issuer certificate

    Encryption certificate

    Verify pin

    Sign

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk PIN Reset

    Authenticate

    Reset pin

    Retrieve supported algorithms

    Validate signature

    Token typings model page
    Supported Algorithms
    Bulk PIN Reset
    export interface AbstractAventra {
    allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
        rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        resetPin(body: TokenResetPinData, callback?: (error: T1CLibException, data: TokenResetPinResponse) => void): Promise<TokenResetPinResponse>
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    
    T1CSdk.T1CClient.initialize(config).then(res => {
        const aventra = res.client.aventra(readerId);
    }, err => {
        console.error(error)
    });
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    aventra.allCertFilters().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate', 'nonRepudiationCertificate', 'issuerCertificate']
    }
    aventra.allKeyRefs().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['authenticate', 'sign', 'encrypt']
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "encryptionCertificates": {
                "certificates": [...]
            },
            "issuerCertificates": {
                "certificates": [...]
            }
       }
    }
    const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
    aventra.allCerts(parseCertsBoolean, filter).then(res => {
        res.data
    }, err => {
        console.error(err)
    })
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    aventra.tokenData().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
           version?: string,
           serialNumber?: string,
           label?: string,
           changeCounter?: number,
        }
    }
    aventra.rootCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.authenticationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.nonRepudiationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.issuerCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.encryptionCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    const data = {
        pin: "1234", // optional
        osDialog: true // optional
    }
    aventra.verifyPin(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            "verfied": true
        }
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        id: "123"
    }
    const bulk = false;
    aventra.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false,
          "id": "1ooidifhv183"
    }
    aventra.signRaw(data, callback);
    aventra.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        id: "123"
    }
    aventra.authenticate(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    const data = {
        pin: "3214", //optional
        puk: "123123"
    }
    aventra.resetPin(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            verified: boolean
        }
    }
    aventra.allAlgoRefs(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            ref: ['sha256', 'md5']
        }
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    safenet.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }

    Oberthur Cosmo One v7.3

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The ID-One Cosmo V7-n is part of the Oberthur family of cryptographic modules called ID-One Cosmo V7. Modules within

    this family share the same functionalities and the description of the ID-One Cosmo V7 applies to all versions including the “-n” subject to this validation.

    This document describes the functionality provided by the Oberthur ID-One smartcard - which is a PKI container:

    • ID-One Cosmo V7-n; FIPS 140-2 Security Policy

    Interface

    export interface AbstractOberthur73 {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
        rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Examples

    Create the Oberthur module

    T1cSdk.initialize(config).then(res => {
        const oberthur = res.client.oberthur(readerId);
    }, err => {
        console.error(error)
    });

    When initialisation is finished you can continue using the aventra object to execute the functions below.

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    The expected response for this call should be;

    The expected response for this call should be;

    Exposes all the certificates publicly available on the smart card. The following certificates can be found on the card:

    • Root certificate

    • Signing certificate

    • Authentication certificate

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    The expected response for this call should be;

    This will return information of the Aventra card.

    The expected response for this call should be;

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Contains the 'root certificate' stored on the smart card. The service can be called:

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:

    The expected response for these calls should be in the following format;

    The expected response for these calls should be in the following format;

    Data can be signed using the smartcard. To do so, the SDK facilitates in:

    • Retrieving the certificate chain (root, intermediate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed has

    To sign data, an algorithm must be specified in the algorithm property (see ), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.

    Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The expected response for this call should be;

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    The SDK is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card

      An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

    The expected response for this call should be;

    The expected response for this call should be;

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Issuer certificate
  • Encryption certificate

  • Token info

    All certificate filters

    Extended certificates

    all Key references

    all Certificates

    Token data

    Certificate

    Root certificate

    Authentication certificate.

    Non repudiation certificate

    Issuer certificate

    Encryption certificate

    Verify pin

    Sign

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk PIN Reset

    Authenticate

    Retrieve supported algorithms

    Validate signature

    Supported Algorithms
    Bulk PIN Reset
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "encryptionCertificates": {
                "certificates": [...]
            },
            "issuerCertificates": {
                "certificates": [...]
            }
       }
    }
    oberthur.allCertFilters().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate', 'nonRepudiationCertificate', 'issuerCertificate']
    }
    oberthur.allKeyRefs().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['authenticate', 'sign', 'encrypt']
    }
    const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
    oberthur.allCerts(filter).then(res => {
        res.data
    }, err => {
        console.error(err)
    })
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    oberthur.tokenData().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
           version?: string,
           serialNumber?: string,
           label?: string,
           changeCounter?: number,
        }
    }
    oberthur.rootCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    oberthur.authenticationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    oberthur.nonRepudiationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    oberthur.issuerCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.encryptionCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    const data = {
        pin: "1234", // optional
        osDialog: true // optional
    }
    oberthur.verifyPin(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            "verfied": true
        }
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        id: "123"
    }
    const bulk = false;
    oberthur.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false,
          "id": "1235s"
    }
    oberthur.signRaw(data, callback);
    diplad.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
        id: "123"
    }
    oberthur.authenticate(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    oberthur.allAlgoRefs(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            ref: ['sha256', 'md5']
        }
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    safenet.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }

    Certinomis*

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks

    Introduction

    The following page describes how you can integrate the Certigna module exposed on the Trust1Connector onto your web application.

    The middleware of Certinomis has to be installed to be able to fully use the Certinomis token.

    Supported version of the middleware is; Windows: 10.6 - & MacOS Catalina and Mojave: MacOS 11 and up:

    Interface

    export interface AbstractCertinomis {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Initialise the Trust1Connector JS

    Initialise a Trust1Connector client with a valid configuration:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Obtain the Reader information

    In order to get all connected card-readers, with available cards:

    var core = client.core();
    core.readersCardAvailable(callback);

    This function call returns:

    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }

    Using the generic interface can be done as follows;

    const moduleName = 'certinomis';
    var client = client.generic(selected_reader.id);

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the certigna integration.

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Token info

    Certificates

    Extended certificates

    Authentication Certificate

    Non-repudiation Certificate

    Filter Certificates

    Sign Data

    Sign Data

    The Certinomis token hashes the data on the token itself. Data to sign needs to be a base64 encoding of the data that needs to be signed.

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    Bulk Sign Reset
    64bit
    32bit
    10.2.97 (supports up until MacOS 10.15 at the time of integration)
    var client = client.camerfirma(selected_reader.id);
    client.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            }
       }
    }
    client.authenticationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.nonRepudiationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    client.allCerts(parseCerts, { filters: filter}, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = ['authenticationCertificate'];
    client.allCerts({ filters: filter}, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = null;
    client.allCerts({ filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"dGVzdA=="
          "osDialog": true
    }
    client.sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    client.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "dGVzdA==",
        pin: "1234"
    }
    const bulk = true;
    client.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    client.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    client.verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {}
    client.verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha256",
      "data":"dGVzdA=="
    }
    client.authenticate(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    client.allAlgoRefs(callback);
    {
        "success": true,
        "data": ["sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    client.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }

    Other PKCS11 Compatible Tokens*

    (prerequisite: driver installation neeeded)

    The following list shows all PKCS11 enabled smart cards or compatible tokens supported by the Trust1Connector. The tokens listed below depends on additional vendor drivers to be installed (typically the pkcs11 interface, OpenSC, ...). Please mail support@trust1team.com if you need support on other smart cards and/or tokens.

    The list is enabled when the 'Truststore' module is available on the Trust1Connector. The 'Truststore' is not by default available and must be activated upfront.

    Smart Card / Token
    Mac OSX
    Windows

    AET Smartcard

    ❌

    ✅

    AKIS

    ✅

    ✅

    Aladdin Knowledge Systems eToken Pro 64k (4.2)

    ✅

    ✅

    Athena ASEPCOS-TS/CNS 1.81

    ✅

    ✅

    Athena ASEPCOS-TS/CNS 1.81

    ✅

    ✅

    Athena ASEPCOS-TS/CNS 1.82

    ✅

    ✅

    Athena IDProtect - Cryptographic Java Card

    ✅

    ✅

    Athena IDProtect Smart Card Logon Card

    ✅

    ✅

    AzeDIT 3.5 cold

    ✅

    ✅

    Bit4ID

    ❌

    ✅

    Brazilian Medical Identity Card

    ✅

    ✅

    Charismathics

    ❌

    ✅

    Datakey 32K PKI Smart Card Model 330

    ✅

    ✅

    Digital Signature Costa Rica (eID)

    ✅

    ✅

    FT ePass2003Auto

    ✅

    ✅

    Gemalto IDBridge CT30

    ✅

    ✅

    Gemalto IDClassic 340

    ❌

    ✅

    Gemalto IDPrime .NET

    ✅

    ✅

    Gemalto IDPrime MD

    ✅

    ✅

    Gemalto IDPrime MD 840 (PKI)

    ✅

    ✅

    Gemalto IDPrime v2+ .NET

    ✅

    ✅

    Gemalto USB Shell Token V2 (37AED46F) 00 00

    ✅

    ✅

    Giesecke & Devrient StarSign USB Token

    ✅

    ✅

    Gnuk OpenPGP Token (PKI)

    ✅

    ✅

    GoldKey Security PIV Token

    ✅

    ✅

    ID Prime 3940B FIDO

    ✅

    ✅

    ID Prime 940

    ✅

    ✅

    ID Prime 940C

    ✅

    ✅

    IDEMIA ID-One CNS V2 on Cosmo V9.1

    ✅

    ✅

    Incard J-Sign 2048

    ✅

    ✅

    Incard J-Sign 2048

    ✅

    ✅

    Individual Number Card

    ✅

    ✅

    Infocamere CNS

    ❌

    ✅

    Italian healtcare card (TS) National Service Card (CNS) (HealthCare)

    ✅

    ✅

    JCOP3 IAS ECC

    ✅

    ✅

    MCARD

    ✅

    ✅

    NXP JCOP J3D

    ✅

    ✅

    National Identity Document: Belgian eID

    ✅

    ✅

    National Identity Document: Broken Estonian eID 1.1 warm

    ✅

    ✅

    National Identity Document: Czech eID (since 7/2018)

    ✅

    ✅

    National Identity Document: Estonian eID

    ✅

    ✅

    National Identity Document: Estonian eID 1.0 cold

    ✅

    ✅

    National Identity Document: Estonian eID 1.0 cold

    ✅

    ✅

    National Identity Document: Estonian eID 1.0 cold 2006

    ✅

    ✅

    National Identity Document: Estonian eID 1.0 warm 2006

    ✅

    ✅

    National Identity Document: Estonian eID 1.1 cold

    ✅

    ✅

    National Identity Document: Estonian eID 3.0 (18.01.2011) warm

    ✅

    ✅

    National Identity Document: Estonian eID 3.0 (dev1) cold

    ✅

    ✅

    National Identity Document: Estonian eID 3.0 (dev1) warm

    ✅

    ✅

    National Identity Document: Estonian eID 3.0 (dev2) warm

    ✅

    ✅

    National Identity Document: Estonian eID 3.5 cold

    ✅

    ✅

    National Identity Document: Nigerian eID

    ✅

    ✅

    National Identity Document: Republic of Lithuania eID

    ❌

    ✅

    National Identity Document: Slovak eID

    ✅

    ✅

    National Identity Document: Spanish eID

    ✅

    ✅

    National Service Card (CNS)

    ✅

    ✅

    Nitrokey Nitrokey HSM

    ✅

    ✅

    Nonus SmartNonus [BR]

    ❌

    ✅

    PIVKey SLE78 (28)

    ✅

    ✅

    PivKey T600

    ✅

    ✅

    PivKey T800

    ✅

    ✅

    Rutoken ECP (DS)

    ✅

    ✅

    SafeNet 5110 (940 B)

    ✅

    ✅

    SafeNet eToken 5100

    ✅

    ✅

    SafeNet eToken 5110

    ✅

    ✅

    SafeNet eToken 5110+ FIPS

    ✅

    ✅

    SafeNet eToken 5110cc

    ✅

    ✅

    SafeNet eToken 5300

    ✅

    ✅

    Safran Morpho YpsID S3

    ✅

    ✅

    Safran Morpho YpsID S3 - French Customs

    ✅

    ✅

    Siemens Card CardOS M4.4

    ✅

    ✅

    StarSign Crypto USB Token

    ❌

    ✅

    Telia EID IP5a (eID)

    ✅

    ✅

    USG:Department of Veterans Affairs

    ✅

    ✅

    USG:Executive Office of the President

    ✅

    ✅

    Yubico Yubikey 4 OTP+U2F+CCID

    ✅

    ✅

    Yubico Yubikey 4 OTP+U2F+CCID

    ✅

    ✅

    Yubico Yubikey NEO OTP+U2F+CCID

    ✅

    ✅

    ePass2003

    ✅

    ✅

    VDDS

    Verband Deutscher Dental Software (VDDS-media 1.4)

    Introduction

    VDDS-media 1.4 defines an interface for the exchange of multimedia data between practice management software and the X-ray/camera software

    The Trust1Connector has a custom `vdds` module which can be used in combination with the `file-exchange` module.

    The `file-exchange` module exposes an API for abstract file management. For more information see: File Exchange. In summary, the `file-exchange` module allows you to define `scoped` abstractions for folders and files, in a web context (based on the origin of the requesting web applciation).

    The additional functionality exposed by the `vdds` module, is mainly:

    • open the Image viewer with a pre-defined image ID

    • import/export data to/from an IPS (Image Processing System)

    The typical client application is a web PMS (Practice Management System).

    The following communication diagram depicts the information exchange defined in the specification:

    The executable names are hard-coded and statically extended to the abstract file descriptor on the T1C-API.

    The HTTP/REST API is used by the T1C-SDK-js (javascript client).

    A file descriptor is defined in terms of the entity and entity type, the absolute path can be used to build a relative folder path starting from the folder mapping (linked to the entity type).

    The supported commands available are denoted in the following enumeration:

    The `vdds` execution endpoint has a single, multi-purpose struct:

    The execution endpoint assumes a proper file management handled by the requesting web application.

    The file-exchange entity, entity-type and thus type-mapping MUST exist prior to the command execution request.

    • the ExecDescriptor contains a field 'argFilePathQuatesDisable', that field basically resolves the file path parameter to a list of strings (split on whitespaces) to simulate passing the argument on a shell, without the double quotes ' " '. Shell execution wraps a file path argument in a C-like string, but some bat or exe files who are not complying to this, can thread the whitespaces in a path as a concatentation of arguments.

    Initialize a Trust1Connector client:

    Get the module using the client

    Now you can use the vdds client to call its functionality.

    The following responses are returned when an exception is thrown:

    • wrong or missing arguments in request body defined by (entity, entity-type, file-name or args)

    • wrong or missing executable path reference defined by (entity, entity-type, command)

    • file-exchange has not been initialized prior to the documented use case

    • referencing file is not found on the local device file system, this is typically the case when a wrong entity-type of relative folder has been provided in the request

    To test the VDDS module execution, you can use a bunch of stubbed executables which are available on [].

    This is nothing fancy, just a cpp repo, which generates 3 executables and dumps the arguments on std::out.

    The testing track described here follow the T1C-API, and does NOT use the T1C-SDK-js !

    If you are using the javascript SDK, you can skip or continue reading to have more insights on how it works *under the hood*.

    Use an REST client of curl to create an entity and entity type -> this will pop-up a file-chooser, where you need to select the folder (where you want the entity-type to link to):

    Response example:

    Custom

    Custom modules

    The Trust1Connector acts as a secured tunnel between an host device and a remote web application.

    This section summarizes custom modules and/or specifications developed in the Trust1Connector

    Integration

    Security Considerations

    Prerequisites

    Interface (T1C-SDK-js)

    Remarks

    Get the VDDS module object

    Import

    Export

    View

    Error Handling

    InvalidInput

    ConfigurationError

    FileNotFoundException

    Testing

    Example 1 - VDDS Import

    Example 2 - VDDS Export

    Example 3 - VDDS Viewer

    github
    https://github.com/Trust1Team/vdds-test-exec
    Overview of VDDS-media
    /// Filepath abstraction for VDDS
    #[derive(Debug, Deserialize, Clone)]
    pub struct FileDescriptor {
        pub entity: String,
        #[serde(rename = "type")]
        pub entity_type: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        #[serde(rename = "relPath")]
        pub rel_path: Option<Vec<String>>,
        #[serde(rename = "fileName")]
        pub file_name: String,
    }
    #[derive(Debug, Clone, Deserialize)]
    pub enum VddsCmd {
        import,
        export,
        view,
    }
    #[derive(Debug, Serialize, Deserialize, Clone, Validate)]
    pub struct VddsExecutable {
        #[validate(length(min = 1, max = 256))]
        #[serde(rename = "entity")]
        pub entity: String,
        #[validate(length(min = 1, max = 256))]
        #[serde(rename = "type")]
        pub entity_type: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        #[serde(rename = "relPath")]
        pub rel_path: Option<Vec<String>>,
        #[serde(rename = "cmd")]
        pub cmd: String, //import, export, view
        #[serde(rename = "argFilePathQuotesDisable")]
        pub arg_file_path_quotes_disable: Option<bool>,
    }
    export interface AbstractVdds {
        import(body: VddsImportRequest): Promise<VddsResponse>;
        export(body: VddsExportRequest): Promise<VddsResponse>;
        view(body: VddsViewRequest): Promise<VddsResponse>;
    }
    
    // Models
    export interface VddsImportRequest {
        exec: ExecDescriptor,
        file: FileDescriptor 
    }
    
    export interface VddsExportRequest {
        exec: ExecDescriptor,
        file: FileDescriptor 
    }
    
    export interface VddsViewRequest {
        exec: ExecDescriptor,
        args: Array<String> 
    }
    
    export interface ExecDescriptor {
        entity: String,
        type: String,
        relPath?: Array<String>
        argFilePathQuotesDisable?: boolean,
    }
    
    export interface FileDescriptor {
        entity: String,
        type: String,
        relPath?: Array<String>
        fileName: String
    }
    
    export class VddsResponse extends T1CResponse {
        constructor(public success: boolean){
            super(success, null);
        }
    } 
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var vdds = client.vdds();
    let body = {
        exec: {
            entity: "Crossuite",
            type: "vdds",
            relPath: ["build"],
        },
        file: {
            entity: "Crossuite",
            type: "vdds",
            relPath: ["files"],
            fileName: "somefile.txt"
        }
    };
    
    vdds.import(body).then(res => {
    // handle response
    }).catch(error => {
    // handle error
    });
    let body = {
        exec: {
            entity: "Crossuite",
            type: "vdds",
            relPath: ["build"],
        },
        file: {
            entity: "Crossuite",
            type: "vdds",
            relPath: ["files"],
            fileName: "somefile.txt"
        }
    };
    
    vdds.export(body).then(res => {
    // handle response
    }).catch(error => {
    // handle error
    });
    let body = {
        exec: {
            entity: "Crossuite",
            type: "vdds",
            relPath: ["build"],
        },
        args: ["rnd_image_id"]
    };
    
    vdds.view(body).then(res => {
    // handle response
    }).catch(error => {
    // handle error
    });
    # InvalidInput
    {
        "success": false,
        "code": 106997,
        "description": "Invalid Input"
    }
    
    # ConfigurationError
    {
        "success": false,
        "code": 505126,
        "description": "Configuration Error"
    }
    
    # FileNotFoundException
    {
        "success": false,
        "code": 505126,
        "description": "File not found"
    }
    
    # checkout
    git clone https://github.com/Trust1Team/vdds-test-exec
    
    # build
    mkdir build
    cd build
    cmake ..
    cmake --build .
    ```powershell
    curl --location 'https://t1c.t1t.io:55000/v3/modules/fileexchange/apps/file/create-type' \
    --header 'X-CSRF-Token: t1c-js' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: ••••••' \
    --data '{
    	"entity": "MyCompany",
    	"type": "vdds",
    	"modal": true
    }'
    ```
    {
        "success": true,
        "data": {
            "entity": "MyComp",
            "type": "vdds",
            "absPath": "/Users/michallispashidis/_git/vdds-test-exec",
            "accessMode": "d",
            "total": 0,
            "appId": "unknown"
        }
    }
    curl --location 'https://t1c.t1t.io:55000/v3/modules/vdds/cmd/exec' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: ••••••' \
    --data '{
        "exec": {
            "entity": "MyComp",
            "type": "vdds",
            "relPath": ["build"],
            "cmd": "import"
        },
        "file": {
            "entity": "Crossuite",
            "type": "vdds",
            "relPath": ["files"],
            "fileName": "somefile.txt"
        }
    }
    '
    {
        "exec": {
            "entity": "MyComp",
            "type": "vdds",
            "relPath": ["build"],
            "cmd": "export"
        },
        "file": {
            "entity": "Crossuite",
            "type": "vdds",
            "relPath": ["files"],
            "fileName": "somefile.txt"
        }
    }
    {
        "exec": {
            "entity": "Crossuite",
            "type": "vdds",
            "relPath": ["build"],
            "cmd": "view"
        },
        "args": ["rnd_image_id"]
    }

    Print

    Introduction

    The Trust1Connector print module provides the integrator the ability to communicate with local printers. It provides an interface to retrieve the available printers and then execute a specific print job on one of those printers.

    Interface

    Below you can find the interface of the Trust1Connector print module.

    export interface AbstractRawPrint {
        list( callback?: (error: T1CLibException, data: PrinterListResponse) => void): Promise<PrinterListResponse>;
        print(name: string, job: string, data: string, callback?: (error: T1CLibException, data: PrintResponse) => void): Promise<PrintResponse>;
    }

    Model Objects

    Below you can find the available models for Trust1Connector print module which are used in the interface.

    export class PrinterList {
        constructor(public printers: Array<string>) {}
    }
    
    export class PrinterListResponse extends T1CResponse {
        constructor(public data: PrinterList, public success: boolean) {
            super(success, data);
        }
    }
    
    export class Print {
        constructor(public printed: boolean) {}
    }
    
    export class PrintResponse extends T1CResponse {
        constructor(public data: Print, public success: boolean) {
            super(success, data);
        }
    }
    

    Get Printer module object

    Before we can use the print module we need to Initialise the Trust1Connector. The code sample below is a simplified version, for the complete initialise flow you can see

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    After you've initialised the Trust1Connector you can use the client/response of the initialise function to instantiate the rawprint module. Later on we can keep using this module to execute various print functions provided by the Trust1Connector interface.

    In the example below we execute the list function available in the rawprint module. Here we use the callback mechanism but a is also available as defined in the interface

    The list function provides an iterator of all the available printers locally. These will return as identifiers that can be used when executing a print action as described in the function

    An example callback:

    Response:

    The Print function available on the interface provides print capabilities via the Trust1Connector. Here you need to specify the print job name, a name for the printer which can be fetched via the function and the Data.

    An example callback:

    The print function will respond with a True or False depending on wether the command succeeded or failed.

    List

    Print

    The data block needs to be base64 encoded.

    Integration in Web Applications
    Promise
    Print
    List
    var print = client.rawprint();
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    print.list(callback);
    client.rawprint().list(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "printers": ["123"],
    }
    const name = "test"
    const job = "test-job-01"
    const data = "SSdtIGRlZmluaXRseSBub3QgYSBNQUxBS0E="
    client.rawprint().print(name, job, data, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "printed": true/false,
    }

    Remote loading

    The ReLo (Remote Loading) container is provided through the T1C (Trust1Connector) in order to provide a secured communication channel to executed APDU commands that are generated from a back-end service (which can be optionally signed by a HSM).

    The ReLo provides smart card operations, like for example:

    • open/close session

    • execute APDUs (single or in bulk)

    Simple Sign

    The response will look like

    The response will look like

    The response will look like

    Wacom*

    Wacom’s Signature can capture handwritten signatures from a pen tablet. The mdoule simplifies the interaction with Wacom pen tablets for signatures.

    The Wacom module supports the STU models which are capable of capturing a handwritten signature.

    The correct driver must be installed:

    Additionally tools are available for Wacom to perform signature analysis:

    Signature Libraries are available for:

    • Windows

    Prerequisites New Token/Smart Card

    Guidlines new Partner token/smart-card or other hardware device

    For a new hardware token to be added to the Trust1Connector framework, we have to take into consideration some necessary prerequisites to assure the development process.

    This article presents an explanatory list for all necessities which are needed before development can start. Please take into consideration especially during pre-sales/sales.

    The artefacts are explained briefly and listed. In order to support and guarantee operations, Trust1Team will need to have all mentioned artefacts at all times.

    The following artefacts are needed to reassure development of a new hardware token:

    Prerequisites Support

    This page will have a description of which prerequisistes are required for technical support via the Support Desk.

    The idea here is that the first-line support requests or retrieves this information from the end customer which is reporting the issue/support.

    To provide proper support we need the following;

    Connector Connection Issues

    This page summarized 'know' solution for connector connection troubleshooting

    The issues described in this document will specifically tackle the following topics;

    • DNS rebind

    • DNS resolving

    • Use of proxy and or firewall

    Functions

    Get SimpleSign module object

    Info

    Initialize context

    Upload file context

    export interface AbstractSimpleSign {
      getInfo(): Promise<GenericT1CResponse<SimpleSignInfoResponse>>;
      initializeContext(origin: string): Promise<GenericT1CResponse<SimpleSignInitializeResponse>>;
      uploadFileContext(origin: string, request: SimpleSignUploadFileContextRequest): Promise<GenericT1CResponse<SimpleSignUploadFileContextResponse>>;
    }
    
    export interface SimpleSignInfoResponse {
      version: string;
      localFolder: string;
    }
    
    export interface SimpleSignInitializeResponse {
      folderBootstrap: string;
      folderExternalUploaded: string;
      folderExternalSigned: string;
      filexOrigin: string;
      filexEntity: string;
      filexTypes: Array<string>;
    }
    
    export interface SimpleSignUploadFileContextResponse {
      origin: string;
      entity: string;
      filename: string;
      callback: string;
      externalId: string;
    }
    
    export interface SimpleSignUploadFileContextRequest {
      filename: string;
      callback: string;
      externalId: string;
    }  
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        let simplesign = client.simplesign();
    }, err => {
        console.error(error)
    })
    simplesign.getInfo();
    {
        "success": true,
        "data": {
            "version": "0.2.5",
            "localFolder": "/Users/someuser/Desktop/simplesign"
        }
    }
    let origin = 'https://acc-rmc.t1t.io';
    simplesign.initializeContext(origin);
    {
        "success": true,
        "data": {
            "folderBootstrap": "/Users/someuser/Desktop/simplesign",
            "folderExternalUploaded": "/Users/someuser/Desktop/simplesign/_uploaded/_external",
            "folderExternalSigned": "/Users/someuser/Desktop/simplesign/_archived/_external",
            "filexOrigin": "https://acc-rmc.t1t.io",
            "filexEntity": "SimpleSign",
            "filexTypes": [
                "UPLOAD",
                "SIGNED"
            ]
        }
    }
    let origin = 'https://acc-rmc.t1t.io';
    let request = {
        "filename": "T1T_test.pdf",
        "callback": "https://test.app",
        "externalId": "123456"
    }
    simplesign.uploadFileContext(origin, request);
    {
        "success": true,
        "data": {
            "origin": "https://acc-rmc.t1t.io",
            "entity": "SimpleSign",
            "filename": "T1T_test.pdf",
            "callback": "https://test.app",
            "externalId": "123456"
        }
    }

    retrieve card/card reader features

  • verify if card present

  • retrieve ATR

  • ...

  • The ReLo-API is an example back-end service implementing different smart card or token profiles (there is no limitation to smart cards). The T1V (Trust1Vault) is a Trust1Team product operating as a secured vault, and integrating with a HSM.

    The following functions are available in the library:

    JavaScript API

    Function

    Input

    Output

    Description

    openSession

    session timeout in seconds

    sessionId

    Opens a remote session, the session will be accessible through a session-id. The T1C will keep the session open and reusable.

    The readerId is passed to theremoteloading handler object on initialization. For example, opening a session on reader with idf56c0ffe15a07d09

    All function return Promises by default.

    If you prefer callbacks, each function also has an optional parameter to pass in a callback function. If a callback function is provided, the function will still return a promise, but the callback function will be called when the promise resolves/gets rejected.

    For any function that accepts a sessionIdparameter, the parameter is optional. If a sessionId is provided, the corresponding session will be used for the request and then will be _kept open_once the request completes. This means that if this was the last request that needed to be made, the session needs to be explicitly closed with a call tocloseSession.

    If no sessionId is provided, the request will still complete, but the GCL will set up a new session, perform the required action and then close the session. This means that there is _no open session_once the request completes.

    When a wrong sessionID is sent in a request, an error message will be returned. The status code will be 'invalid sessionID' or 'no active session'

    Opens a new session. Returns the sessionId, which will need to be stored by the client application for later use.

    • timeout (optional): session timeout in seconds. If not provided, will default to value set in GCLConfig. Must be a number > 0.

    Sends a command to the reader for execution.

    command(tx: string, sessionId?: string, callback: (error, data))

    • tx: command-string to be executed

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    Activates a specific CCID feature if it is available on the reader

    ccid(feature: string, command: string, sessionId?: string, callback?: (error, data))

    • feature: feature to check

    • command: command to send to the ccid reader (hex format)

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    Closes currently open session.

    closeSession(callback?: (error, data))

    • none

    Checks if the card for this session is still present.

    If no sessionId is provided, checks if a card is present in the reader.

    isPresent(sessionId?: string, callback?: (error, data))

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    Retrieves the ATR for the card currently in the reader.

    atr(sessionId?: string, callback?: (error, data))

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    Returns a list of available CCID features for the current reader.

    ccidFeatures(sessionId?: string, callback?: (error, data))

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    Executes an APDU call on the current reader. The difference with the commandfunction is that theapdu function takes an APDU object, whereas commandtakes a string.

    apdu(apdu: ApduObject, sessionId?: string, callback?: (error, data))

    • apdu: object containing the APDU to be executed

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    APDU Object interface:

    For the apduand commandfunctions, it is possible to send an array of apdu's/commands.

    Executes an array of APDU calls on the current reader.

    apdus(apdu: ApduObject[], sessionId?: string, callback?: (error, data))

    • apdu: array containing the APDU objects to be executed

    • sessionId (optional): sessionId to use. Required if the session needs to be kept open after the request completes.

    APDU Object interface:

    Executes an array of commands on the current reader.

    commands(tx: string[], sessionId?: string, callback?: (error, data))

    • tx

      : array containing the command strings to be executed

    • sessionId

      (optional)

      : sessionId to use. Required if the session needs to be kept open after the request completes.

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    interface AbstractRemoteLoading {
        atr(sessionId?: string, callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
        apdu(apdu: APDU, sessionId?: string, callback?: (error: T1CLibException, data: CommandResponse) => void): Promise<CommandResponse>;
        apdus(apdu: APDU[], sessionId?: string, callback?: (error: T1CLibException, data: CommandsResponse) => void): Promise<CommandsResponse>;
        ccid(feature: CCIDFeature, command: string, sessionId?: string, callback?: (error: T1CLibException, data: CommandResponse) => void): Promise<CommandResponse>;
        ccidFeatures(sessionId?: string, callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
        command(tx: string, sessionId?: string, callback?: (error: T1CLibException, data: CommandResponse) => void): Promise<CommandResponse>;
        commands(tx: string[], sessionId?: string, callback?: (error: T1CLibException, data: CommandsResponse) => void): Promise<CommandsResponse>;
        closeSession(sessionId?: string, callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
        isPresent(sessionId?: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        openSession(timeout?: number, callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
    }
    export enum CCIDFeature {
        VERIFY_PIN_DIRECT = 'VERIFY_PIN_DIRECT',
        MODIFY_PIN_DIRECT = 'MODIFY_PIN_DIRECT',
        GET_TLV_PROPERTIES = 'GET_TLV_PROPERTIES'
    }
    openSession(timeout?: number, callback?: (error, data))
    {
        data: string // sessionId string
        success: boolean
    }
    {
        data: {
            tx: string, // input
            rx?: string, // output
            sw: string  // status word
        }
        success: boolean
    }
    {
        data: string // ccid response
        success: boolean
    }
    {
        success: true
    }
    {
        data: boolean // true if present, false if not
        success: boolean
    }
    {
        data: string // ATR string
        success: boolean
    }
    {
        data: Ccid[]
        success: boolean
    }
    {
        cla: string
        ins: string
        p1: string
        p2: string
        data?: string
        le?: string
    }
    {
        data: {
            tx: string, // input
            rx?: string, // output
            sw: string  // status word
        }
        success: boolean
    }
    {
        cla: string
        ins: string
        p1: string
        p2: string
        data?: string
        le?: string
    }
    {
        data: {
            tx: string, // input
            rx?: string, // output
            sw: string  // status word
        }[] // Array of response objects
        success: boolean
    }
    {
        data: {
            tx: string, // input
            rx?: string, // output
            sw: string  // status word
        }[] // Array of response objects
        success: boolean
    }

    Communication Flow

    Available functions

    ReaderId

    Callback/Promise

    SessionID is optional

    Interface

    Objects

    Detailed Function Overview

    openSession

    The sessions are opened in shared mode

    Interface

    Parameters

    Output

    command

    Interface

    Parameters

    Output

    ccid

    Interface

    Parameters

    Output

    closeSession

    Interface

    Parameters

    Output

    isPresent

    Interface

    Parameters

    Output

    atr

    Interface

    Parameters

    Output

    ccidFeatures

    Interface

    Parameters

    Output

    apdu

    Interface

    Parameters

    Output

    Bulk Actions

    apdus (bulk)

    Interface

    Parameters

    Output

    commands (bulk)

    Interface

    Parameters

    Output

    Model
    Pressure levels
    Sampling rate
    Max. resolution
    Active screen area
    I/O
    Monochrome/colour

    STU-300*

    512

    200 Hz

    Models marked with a "*" are no longer in production

    Download and run Wacom-STU-Driver-5.4.5.exe

    Requirements

    The driver is required to use colour STU signature pads with the STU SDK and Wacom Signature SDK. The driver is also required when using any STU signature pad on Windows 8 or 8.1.

    Summary

    The driver is required for the colour display STU signature pads and also when using any of the STU signature pads on Windows 8.1. It allows the device to use USB Bulk Transfer to handle the transfer of increased image data size (compared with the mono STU tablets). On Windows 8 and 8.1 it also disables the Enhanced Power Management setting.

    The driver installation merely configures the USB interface for the STU tablet and can be used in all configurations without any detrimental effect.

    When using the Trust1Connector, the driver must always be installed.

    Wacom Signature Components

    The Signature Library creates a Signature Object to hold a captured signature. A signature can be handled by an application in its native binary format (Forensic Signature Stream - FSS) or in the Base64 text encoded format such as the following example:

    The Signature Object contains the following data:

    • Name

    • Reason

    • Date timestamp

    • Application specific data

    • System information

    • Pen data

    Data is stored in the Signature Object in an undisclosed proprietary format and API is provided to extract parts of it:

    • Name

    • Reason

    • Date timestamp

    • Application specific data

    One type of application specific data is the hash of a signed document. Before starting signature capture the application can calculate a hash value for the document and include it in the signature data. At a later time the application can recalculate the hash and use the API to compare the new and saved values to determine whether any changes have been made since signing. The results can then be used to indicate the validity of a signature.

    API is not provided to extract the pen data because this is personal information which could be used fraudulently. When legitimate access to the full data is needed, such as when the authenticity of a signature is assessed by a qualified Forensic Document Examiner, this is possible using the SignatureScope application (see link in the references).

    Error
    HTTP code
    Description

    WacomListDeviceException

    404

    Can not connect to the Wacom device

    WacomSysInfoException

    404

    Below you can find the interface of the Trust1Connector print module.

    Below you can find the available models for Trust1Connector print module which are used in the interface.

    Before we can use the wacom module we need to Initialise the Trust1Connector. The code sample below is a simplified version, for the complete initialise flow you can see

    After you've initialised the Trust1Connector you can use the client/response of the initialise function to instantiate the wacom module. Later on we can keep using this module to execute various wacom functions provided by the Trust1Connector interface.

    In the example below we execute the getDevices function available in the rawprint module. Here we use the callback mechanism but a Promise is also available as defined in the interface

    The getDevices function provides an iterator of all the available wacom tablets locally. These will return as identifiers that can be used when executing a signData action

    An example callback:

    Response:

    The system info endpoint provides a way to get more information about the wacom devices connected and the wacom driver installed

    An example callback:

    Response;

    The wacom interface provides a way to sign using the wacom tablets.

    An example callback:

    Response;

    Signature Compatibility

    STU Device Specifications

    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
    export interface AbstractWacom {
        signData: (body: WacomSignDataRequest, callback?: () => void) => Promise<WacomSignDataResponse>
        getDevices: (callback?: () => void) => Promise<WacomGetDevicesResponse>
        systemInfo: (callback?: () => void) => Promise<WacomSystemInfoResponse>
    }
    export class WacomDevice {
        constructor(public name: string,
                    public type: string,
                    public model: string,
                    public width: number,
                    public height: number,
                    public certificate?: string) {
        }
    }
    
    export class WacomGetDevicesResponse {
        constructor(public data: Array<WacomDevice>, public success: boolean) {
        }
    }
    
    export class WacomSignDataRequest {
        constructor(public name: string, public reason: string, signer: string, hash: string, image: WacomImage) {
        }
    }
    
    export class WacomImage {
        constructor(
            public data: string,
            public rectX: number,
            public rectY: number,
            public rectW: number,
            public rectH: number
        ) {
        }
    }
    
    export class WacomPackage {
        constructor(
            public component: string,
            public version: string
        ) {
        }
    }
    
    export class WacomSignDataResponse {
        constructor(public data: WacomSignDataResponseData, public success: boolean) {
        }
    }
    
    export class WacomSignDataResponseData {
        constructor(public image: string, public metadata: Array<{ string: string }>) {
        }
    }
    
    export class WacomSystemInfoResponse {
        constructor(public data: WacomSystemInfoResponseData, public success: boolean) {
        }
    }
    
    export class WacomSystemInfoResponseData {
        constructor(public device_list: Array<string>, public package_list: Array<WacomPackage>) {
        }
    }
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var wacom = client.wacom();
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    wacom.getDevices(callback);
    client.wacom().getDevices(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    export class WacomDevice {
        constructor(public name: string,
                    public type: string,
                    public model: string,
                    public width: number,
                    public height: number,
                    public certificate?: string) {
        }
    }
    
    export class WacomGetDevicesResponse {
        constructor(public data: Array<WacomDevice>, public success: boolean) {
        }
    }
    client.wacom().systemInfo(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    export class WacomSystemInfoResponse {
        constructor(public data: WacomSystemInfoResponseData, public success: boolean) {
        }
    }
    
    export class WacomSystemInfoResponseData {
        constructor(public device_list: Array<string>, public package_list: Array<WacomPackage>) {
        }
    }
    
    export class WacomPackage {
        constructor(
            public component: string,
            public version: string
        ) {
        }
    }
    let body = {
     name: "wacom1",
     reason: "signing some document",
     signer: "test user",
     hash: "...hash to sign..."
    }
    client.wacom().signData(body, callback)
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    export class WacomSignDataResponse {
        constructor(public data: WacomSignDataResponseData, public success: boolean) {
        }
    }
    
    export class WacomSignDataResponseData {
        constructor(public image: string, public metadata: Array<{ string: string }>) {
        }
    }

    STU Driver

    Overview of Signature SDK Components and Flow

    Signature Object

    Signature Data

    Exception Handling

    Interface

    Model Objects

    Get Wacom module object

    GetDevices

    System info

    Sign data

    Minimum of 2 test cards (valid, expired, …) with corresponding access codes
  • Chip/card specifications (interface)/Operating system details (context) f

  • Specifications of the personalisation of the card [Card Perso Documentation containing APDU commands]

  • Interface Information

  • [Optionally - depending on requirements] Card reader used by customer

  • Operating Systems

  • Test cards are need to:

    • use the test cards during development, and especially for:

      • card communication development

      • card application development

      • card security layer development

    • use the test cards during integration testing:

      • Level 1: APDU Tracing/Testing

      • Level 2: Sandboxed service layer testing

    A test card guarantees the solution is developed correctly and tested before releasing the artefact in production.

    Artefact: physical test cards/hardware tokens in different variations delivered to T1T

    Smart-cards or hardware tokens are typically issued by a CA (Certificate Authority), using chips from industrial chip manufacturers. The chip manufacturers are issuing chips with global specifications. Issued chips can have one or more interfaces, sometimes on one single chip on or 2 chips. Typically a combination between contact and/or contactless interfaces.

    The global specifications gives information about the following topics:

    • The operating system used on the chip

    • The security information needed to access the card context

    • The security information needed to access the card applications

    • The security algorithms for key exchange

    • …

    Artefact: a digital document shared with T1T with information on the chip/card specifications. They typically contains APDU statements and sequence diagrams

    Personalisation is the process done when issuing a smart-card for production. This is, the hardware is initialised for a specific user, following a template depending on the business context.

    The personalisation phase is the phase where custom/specific data/certificates or other data is persisted on the card. Besides the data persistence, the state of the card is set and interfaces are secured.

    The personalisation specifications, explain what and how data is stored on the card, the state of the card, and the way that it impacts the interfacing.

    In short, the chip/card specifications in step 2, along with the personalisation specifications mentioned above, define the bleu-print of a personalised production card.

    Artefact: Personalisation Specifications, a document that states typically how a card has been initialised for production

    All available information on the interface with the card/chip. The following questions should be answered:

    • Is there a PKCS 11 interface?

    • Is there a need for integration with MSCAPI, CNG, ..

    • Is there a custom defined interface?

    • Do we need to use a custom external libraries (.dll’s for example) for the integration?

    When one of the above questions results in ‘yes’:

    • deliver the external library with its interface (when cpp: dll and header files)

    Artefact: General information optionally enriched with external libraries (including their interfaces)

    Depending on the requirements of the customer, it’s possible that the business context demands a specific card reader. This is for example the case in the financial domain. Card readers can have additional security keys, which prevents hardware tokens to be used elsewhere (read::on other card readers).

    When this is the case, it is necessary to have a card reader in order to develop and test.

    Artefact: Optional card reader for development and testing

    Customer requirements for the operating system used in customer base:

    • Linux (Debian, Ubuntu, CentOS, …)

    • Windows (only officially supported and NOT EOL)

    • Mac (NOT EOL)

    Introduction

    Instructions

    1. Test Cards

    2. Chip/Card specifications

    3. Personalisation Specifications

    4. Interface Information

    5. [Depending on Customer Requirements] Card Reader

    6. Operating Systems

    Information of the installed/used Trust1Connector
  • information of the Operating system used

  • Bundle all this information and send this to our service desk

    To provide support we do require some information about the issue, a concise but complete description of the issue that the end-user is facing helps us understand what the user is trying to do and what components could be the culprit.

    This also includes a short but descriptive title for the issue/bug you want to log

    For support in regards of the Trust1Connector we need the following information;

    • Trust1Connector Version installed

    • Trust1Connector SDK version used in the web application

    • Trust1Connector log files

    • which shows what actions have been triggered on the web application (optional)

    The following items that are required will be in the context of the operating system and network situation.

    • Which operating system is being used (Windows, MacOS, Linux)

    • Which architecture is the System? (x64, x86, ARM,...)

    • Which version (including build for windows/MacOS) is used

    • Does the user use a VPN or a Proxy on his system

    • Is the user connected to a corporate network where various policies are enforced

    • Are there any Group policies applied?

    • Is the user logged in on a Remote Desktop machine

    • Event viewer/Console.app logs regarding the trust1connector

    Issue description

    Issue description

    Trust1Connector information

    Operating system information

    DNS rebinding is a method of manipulating resolution of domain names. In the case of the Trust1Connector we use a domain to resolve to localhost or 127.0.0.1. We do this because Self signed certificates are not allowed by browsers and using an insecure protocol from a secured website is not allowed either.

    Some routers prevent DNS rebind, the name for this is DNS rebind protection. They will prevent domains that resolve to private network ip's, such as 127.0.0.1.

    For the Trust1Connector to work this settings must be disabled or the domain t1c.t1t.io must be whitelisted. How to do this should be provided in documentation from your ISP or Router vendor.

    In some cases customers will have their own custom DNS server for various reasons. When this DNS server does not have the domain t1c.t1t.io which should resolve to 127.0.0.1 it can cause the customer to prevent using the software.

    The issue will typically show up as "Could not find the installation".

    To resolve this the domain should be either resolved by the DNS server or the hosts file should be updated.

    Modifying your hosts file enables you to add a fallback to the domain name system (DNS) for a domain on a specific machine.

    Modifying your hosts file causes your local machine to fall back to the Internet Protocol (IP) address that you specify.

    Modifying the hosts file involves adding an entries to it. The entry contains the IP address to which you want the DNS to resolve and a version of the Internet address.

    When the connector is not reacting, but the installation has succeeded, a DNS Rebind policy can forbid the communication form a web application to the connector's domain name. The default domain name used is: t1c.t1t.io

    Other than DNS rebind, a DNS server not containing the necessary resolutions for localhost or t1c.t1t.io can cause the same issues as a DNS rebind problem.

    There are 2 approaches to fix DNS rebind issues:

    1. update the 'host' file of the device (needs admin rights)

    2. update the local router which enforces the DNS Rebind

    And 2 for when the configured DNS server does not contain the name resolutions;

    1. update the 'host' file of the device (needs admin rights)

    2. Ask the network administrator to update the DNS server to include name resolutions for localhost and t1c.t1t.io to 127.0.0.1

    The admin password will be asked in the command line. If you open the file with another editor, a pop-up will ask you for the administrator password.

    The file will be shown (the example can be different from what is configured on your device)

    We need to add an additional line to this file:

    Open Notepad or an editor of choice and run as administrator the following file:

    The contents will look like this

    We need to add an additional line to this file:

    Select File > Save to save your changes. Restart your browser

    When updating the local host file is not resolving the connectivity issue, that usually means that the DNS server is blocking the translation of the domain address to a localhost IP.

    We recommend allowing/white listing the domain name for DNS Rebind Protection. If that is not possible, you can opt to update the DNS configuration to the default browser configuration. This can happen when you ISP router is blocking the traffic at home.

    Open Windows Powershell as 'administrator'. You can do that by searching for Powershell and mouse-right-click on the startup icon > 'Open as administrator'

    You first need to know on which connection interface you want to 'set/configure' the DNS settings. The first command will list all available internet connection interfaces:

    Each internet connection interface is numbered. Use the dedicated number for your connection as an input parameter of the 'set/configure' DNS command:

    The above command sets some default DNS server addresses (Google and/or Cloudflare), but off course you can update the list with the values you prefer.

    When executing the above command, no restart is needed and the connection issue to the connector will be sovled.

    In some cases there is need for a proxy service by the organization or network. Here this setting can be enforce on a System level and on a browser level. On the system level this can be applied via the settings of the Operating system but can also be applied by policies (GPO) from the infrastructure/network.

    There is a protocol that can do domain resolution based on a Proxy PAC file, which is used by browsers specifically, this is a Javascript file which is hosted on the network infrastructure for browsers to download and execute to determine domain name resolution.

    Another typical case we see is where a firewall is defined which can have certain rules preventing the Trust1Connector to function. For this we ask the administrator to make sure that the following points are tackled;

    • The domain(s) should be reachable (t1c.t1t.io and ds.t1t.eu)

    • The program is running on 3 TCP ports, 51983 and 2 dynamically allocated ones, we ask to have the default port (51983) to be allowed by the firewall

    An anti-virus has functionalities to protect you from malicious software components. When an anti-virus is present on your device, please allow the connector processes to be trusted and allowed to connect to the web.

    More information on 'known' solution for anti-virus services can be found: Troubleshooting

    DNS Rebind Protection

    // open the host file (write enabled)
    // use your own editor of choice
    sudo nano /etc/hosts
    ##
    # Host Database
    #
    # localhost is used to configure the loopback interface
    # when the system is booting.  Do not change this entry.
    ##
    127.0.0.1       localhost
    255.255.255.255 broadcasthost
    ::1             localhost
    // add these line
    127.0.0.1       t1c.t1t.io
    127.0.0.1       localhost
    c:\Windows\System32\Drivers\etc\hosts
    # Copyright (c) 1993-2009 Microsoft Corp.
    #
    # This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
    #
    # This file contains the mappings of IP addresses to host names. Each
    # entry should be kept on an individual line. The IP address should
    # be placed in the first column followed by the corresponding host name.
    # The IP address and the host name should be separated by at least one
    # space.
    #
    # Additionally, comments (such as these) may be inserted on individual
    # lines or following the machine name denoted by a '#' symbol.
    #
    # For example:
    #
    #      102.54.94.97     rhino.acme.com          # source server
    #       38.25.63.10     x.acme.com              # x client host
    # localhost name resolution is handle within DNS itself.
    #       127.0.0.1       localhost
    #       ::1             localhost
    // add these line
    127.0.0.1       t1c.t1t.io
    127.0.0.1       localhost
    Get-DnsClientServerAddress
    Set-DnsClientServerAddress -InterfaceIndex {your_interface_ref_number} -ServerAddresses ("8.8.8.8","1.1.1.1")

    DNS Resolving

    Hosts file

    Make sure you start your text editor (notepad or other) with ADMIN rights. If not you are more likely to create a second host file which will not solve the issue.

    When using notepad, make sure - when opening a file - you change the file filter in the explorer window to *.*

    The host file does not have a .txt extension.

    On Windows the host file is typically located on the following path:

    Update the 'host' file on the device

    [MAC OSX]

    [WINDOWS]

    Update DNS Settings

    Windows

    A proxy is defined

    Antivirus

    Level 3: Local Service Integration testing
  • Level 4: Web Integration testing

  • C:\Windows\System32\Drivers\etc\hosts

    HAR file

    command

    tx, sessionId (optional)

    command response

    A single command to be executed remotely. When no session is available, a new session will be opened and immediately closed after execution of the command.

    commands

    tx[], sessionId (optional)

    command response[]

    One or more command to be executed remotely and sequentially. When no session is available, a new session will be opened and immediately closed after execution of the commands.

    ccid

    feature, command, sessionId (optional)

    ccid response

    Trigger a specific CCID feature.

    closeSession

    N/A

    N/A

    Close a session. When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    isPresent

    sessionId (optional)

    boolean

    Verify if a card is present. When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    atr

    sessionId (optional)

    ATR for card

    Retrieve ATR from card. When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    ccidFeatures

    sessionId (optional)

    list of features

    List of card readers features available for CCID. When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    apdu

    apdu object, sessionId (optional)

    apdu response

    Execute a single APDU command. When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    apdus

    apdu[], sessionId (optional)

    apdu response[]

    Execute one or more APDU commands (APDU bulk). When no session is available, a new session will be opened and closed. The T1C will be in its initial state.

    396 x 100

    99 x 25 mm

    USB

    Monochrome

    STU-300B

    512

    200 Hz

    396 x 100

    99 x 25 mm

    USB

    Monochrome

    STU-430

    1024

    200 Hz

    320 x 200

    96 x 60 mm

    USB

    Monochrome

    STU-430V

    1024

    200 Hz

    320 x 200

    96 x 60 mm

    Serial

    Monochrome

    STU-500*

    512

    200 Hz

    640 x 480

    102 x 76 mm

    USB or serial

    Monochrome

    STU-520*

    512

    200 Hz

    800 x 480

    104 x 60 mm

    USB

    Colour

    STU-530

    1024

    200 Hz

    800 x 480

    108 x 65 mm

    USB

    Colour

    STU-540

    1024

    200 Hz

    800 x 480

    108 x 65 mm

    USB or serial

    Colour

    STU-541

    1024

    200 Hz

    800 x 480

    108 x 65 mm

    USB

    Colour

    Can not connect to the Wacom device (check if driver has been installed)

    WacomSignException

    417

    Can not proceed the sign operation, although all parameters are provided

    Integration in Web Applications

    MacOS Rosetta

    Overview

    With the latest systems of Apple they have switched over from Intel to Arm processors. Apple has provided a translation layer between application that are compatible with Intel but not with Arm.

    In the Trust1Connector we have 1 component which relies on this translation layer for some functionality.

    Problem

    During installation on these systems it can show as a "successfull installation" but the installation folder is still missing.

    in the console logs it will show an error that an installation of Rosetta 2 is necessary.

    Solution

    The solution is to enable rosetta 2 and then re-install the Trust1Connector application.

    you can enable Rosetta 2 with the following command (administrative password is required)

    sudo softwareupdate --install-rosetta

    Disable DNS rebind pop-up

    The Trust1Connector by default will check and see if a DNS rebind issue has been detected or not.

    If this is the case it will try to add a line to the hostfile. This file requires administrative rights to update so a pop-up will appear.

    This will look like the following in windows.

    If you want to prevent this from happening you can update the Registry key to disable this

    The following table indicates which key must be updated with which value

    Installer type
    Key location
    Key name
    Key value

    C:\Program Files\Trust1Connector\t1c-launch.exe --env prod --silent --fix.dns.rebind false

    Default

    Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

    Trust1Connector API

    C:\Users\{YOUR_USERNAME}\AppData\Local\Trust1Connector\t1c-launch.exe --env prod --silent --fix.dns.rebind false

    Standalone

    Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

    Trust1Connector API

    C:\Users\{YOUR_USERNAME}\AppData\Local\Trust1Connector\t1c-launch.exe --env prod --silent --fix.dns.rebind false

    Admin

    Computer\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

    A reboot is required for this to take into account

    Trust1Connector API

    Chrome LNA update 28-10-2025

    In this document the impact of the Google Chrome update of 28-10-2025 on the Trust1Connector is discussed. Apart from the impact for service desks and end-users you will also find all necessary information to adapt your configuration.

    What was updated?

    Chrome has updated its Local Network Access Restrictions.

    What is Local Network Access?

    Local Network Access restricts the ability of websites to send requests to servers on a user's local network (including servers running locally on the user's machine), requiring the user grant the site permission before such requests can be made. The ability to request this permission is restricted to secure contexts.

    Why does Local Network Access needs restrictions?

    Chrome is adding a new permission prompt for sites that make connections to a user's local network as part of the Local Network Access specification. The aim is to protect users from cross-site request forgery (CSRF) attacks targeting routers and other devices on private networks, and to reduce the ability of sites to use these requests to fingerprint the user's local network.

    More technical information and official release notes of Google can be found here.

    Why is the Trust1Connector impacted?

    The Trust1Connector is using the local system of the user. This is one of the fundaments of the Trust1Connector. It runs decentralized in the userspace of the computer.

    The new update of Chrome is preventing the browser to connect to the local system except if security policies are respected and previous security were done. Malicious websites are not able to address the connector from a browser. Trust1Team has of course implemented these updates already.

    The end-user will get a pop-up that requests permission for local access. Just click ‘allow’ and the connector will run smoothly.

    There is NO need for a new version starting from version 3.8.x and up. As always we advise you to update to the latest version of the Trust1Connector which is version 3.8.8. If you are using the default version of the Trust1Connector then all clients are automatically updated with the latest version via our Distribution Server.

    There is an impact if you work with iframes. Please read the following in which the problem and resolutions are described.

    If you have selected 'Block' during the screen shown above, that means that the connector will not be able to connect to the browser. To revert that back:

    • use the "Clear browsing data" tool (Ctrl+Shift+Del or Menu > History > Clear browsing data), select "All time" for the time range, check boxes for "Cookies and other site data" and "Cached images and files," and click "Clear data," which signs you out of accounts and requires a browser restart.

    A last resort solution is to disable 'Local Network Access' temporary.

    In the browser type in the following URL: chrome://flags

    In the top search bar of the page, search for: 'Local Network Access'

    And set all selectors to 'disabled'

    Setting this disables the feature updated in Chromium browsers for local network access

    End-user impact

    Impact for service desks and partners

    What if I selected 'Block' and want to revert that decision?

    You must close all browser windows, and restart the browser

    What if after following the steps above, it is still not working?

    The same applies for browsers: EDGE, BRAVE AND OTHER CHROME BASED BROWSERS

    release note

    Setting up the SDK

    Include Trust1Connector JS SDK

    Include the Trust1Connector JavaScript SDK on your web application. This will provide you with access to the SDK's functions which are used to execute the Trust1Connector's functionality.

    From now on we will refer to the Trust1Connector JS SDK to the following variances;

    • T1C-js/t1cjs

    • T1C SDK

    Using Trust1Connector in as a library

    The Trust1Connector is a Javascript Library with TypeScript typings. This can be easily used in any web-application by loading the javacript files on the web-page.

    Loading the T1C SDK onto a web-page can be done as shown in the code example below of a html page

    In the example you can see that we load the Javascript SDK on line 8

    The defer attribute means that the script will be downloaded in parallel with the rest of the web-page but will be executed when the page has finished loading in.

    This is mostly used to make sure that when the Javascript wants to target a specific element on the page, for example a div, that this element has already been loaded and is accessable.

    We also provide an npm package that makes it easier to load and use the Trust1Connector Javascript SDK as a module.

    Using Trust1Connector as a module

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script defer src="./T1CSdk.js"></script>
    </head>
    <body>
        ...
    </body>
    </html>
    <script defer src="./T1CSdk.js"></script>

    Installation FAQ

    Where can I find the installed files

    Windows

    The Trust1Connector API will be located in %localappdata%/Trust1Connector/

    MacOS

    The API will be located in

    ~/Library/Application Support/Trust1Team/Trust1Connector/

    Do I need administrator rights for installation

    For the Trust1Connector API you do not need any administrator rights.

    How can I manually restart the API?

    Windows

    The Windows version of the Trust1Connector can be started with the Launcher executable provided. More information can be found

    MacOS

    First unload and stop the services. The first is the API and the second is for card communication;

    launchctl unload ~/Library/LaunchAgents/com.t1t.t1c.api.plist

    Now load the service again which will make it restart

    launchctl load ~/Library/LaunchAgents/com.t1t.t1c.api.plist

    The log files have the same name in both Windows as MacOS;

    • t1c-api.log

    • t1c-reg.log

    • sandbox_log.txt

    %localappdata%/Trust1Connector/

    ~/Library/Application Support/Trust1Team/Trust1Connector/

    Where can i find the log files

    Windows

    Macos

    Intune Installation

    From v3.8.10 (admin installer)

    Trust1Connector — Intune / MDM Deployment Guide

    Audience: DevOps engineers managing Microsoft Intune or similar MDM platforms at customer sites. Scope: Windows deployment of the Trust1Connector (T1C) MSI package — architecture overview, certificate trust chain, installation, uninstallation, and troubleshooting.


    Package Variants — Default vs Standalone

    Two MSI flavours are published for every release:

    Variant

    MSI name pattern

    The only functional difference is the presence of t1c-reg.exe (Device Registry daemon). All other binaries, the Root CA flow, and the Intune deployment steps are identical. Sections below note where behaviour differs between variants.


    1. Architecture Overview

    2. Process Model

    3. Filesystem Layout

    4. Root CA — What It Is and Why It Matters


    The Trust1Connector is a per-machine Windows service that exposes a local HTTPS API on https://localhost:51983. Browser extensions and web applications call this API to access smart cards and cryptographic hardware attached to the device.

    The connector listens only on localhost — no inbound network traffic is involved. TLS on localhost is provided by a self-signed Root CA generated locally per device. That CA must be trusted at the machine level before any browser will accept the connection.


    Executable
    Role
    Started by

    Note: For other client packages (t1c-api.exe, t1c-sandbox.exe, etc.) the binary names differ but the role model is identical.

    The API runs under the SYSTEM account (inherited from the MSI install context), which gives it the privileges needed to install the Root CA into the machine-wide trust store without prompting the end user.


    The per-package LocalAppData folder is not managed by Windows Installer. The MSI explicitly deletes it on uninstall via a custom action. On upgrade it is intentionally preserved so device keys and sync state survive. The shared T1CConnector folder is never deleted by any single package uninstaller — it is preserved so other installed packages (*Connector, etc.) can continue to reuse the same Root CA.


    The connector serves its REST API over HTTPS on localhost. Modern browsers (Chrome, Edge, Firefox) require a valid certificate chain for any HTTPS connection — even to localhost. A self-signed leaf certificate is rejected by default. The solution is a locally-generated Root CA that is trusted at the machine level, which then signs the localhost TLS certificate.

    On first startup after installation the API (t1c-api.exe) automatically:

    1. Generates a 4096-bit RSA key pair for the Root CA.

    2. Issues a self-signed CA certificate with:

      • Common Name: T1C Local Root CA

    Trust store
    Who sees it
    Elevation needed
    Dialog for user

    For enterprise / Intune deployment the cert must be in LocalMachine\Root:

    • No per-user prompts (zero end-user interaction).

    • Works for all users on shared or multi-user devices.

    • Survives user profile resets.

    • Compatible with browser enterprise policies that block

    Because the connector runs as SYSTEM when launched by the MSI, certutil -addstore Root (targeting LocalMachine\Root) succeeds without any UAC prompt. If for any reason the machine-level install fails, the API falls back to CurrentUser\Root (acceptable for single-user devices; see §10 for manual remediation).

    Before installing, the API computes the SHA-256 thumbprint of the CA file on disk and queries both LocalMachine\Root and CurrentUser\Root using PowerShell:

    If the exact certificate is already present the install step is skipped — no duplicate entries are created. If a stale entry exists with the same CN but a different thumbprint (from a previous installation), it is removed before the new one is added.


    The following diagram shows the full sequence from Intune deployment to a browser-trusted HTTPS connection.

    • The MSI must be deployed in system context (not user context) — see §6.

    • The entire flow is silent: no dialogs, no user interaction.

    • The Root CA install happens twice (API at startup + MSI commit action) for reliability.


    Deploy as a Line-of-Business (LOB) app using the .msi file directly, or wrap it with the for a .intunewin package (recommended for better reporting).

    Setting
    Required value
    Reason

    If you deploy in User context the Root CA will land in CurrentUser\Root for the Intune service account (not the end user), which no browser will read. Always use System context.

    For the standalone variant:

    The GUID above is for Trust1Connector. Other client packages have different UpgradeCodes — confirm from the package metadata.

    Use one of the following:

    Option A — Registry (recommended)

    Option B — File

    Option C — Certificate (confirms end-to-end success)

    Run as a custom detection script:

    Rule
    Value

    If your tenant enforces "Prevent users from installing root certificates" (HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\Root\ProtectedRoots = 1), this blocks certutil -addstore Root even for SYSTEM. You will need to either:

    • Exempt the device group from that policy, or

    • Pre-deploy the Root CA via Intune's Trusted Certificate profile (see §10).


    Run these commands on the device (or via Intune Remediations / PowerShell script):

    All four checks (1–4) should succeed for both variants. Check 5 applies only to the default (non-standalone) package. If check 1 fails but checks 2 and 4 pass, run the manual fallback in §10.


    After uninstall the device is in a completely clean state — no orphaned processes, no leftover certificates, no leftover files.

    Set the uninstall command above in the app's Uninstall command field. Assign to a device group with Uninstall intent.

    or use Settings → Apps → Installed Apps → Trust1Connector → Uninstall.

    • The Windows Startup Run key is removed by the MSI component.

    • The %LocalAppData%\T1CConnector\ shared cert folder — preserved so other packages on the same device are not broken.

    • Firefox NSS stores (if Mozilla Firefox was used) — the Firefox certutil removes the CA from Firefox profiles automatically; if it fails, Firefox will simply show a certificate warning again on next use.


    The MSI uses MajorUpgrade — installing a newer version over an existing one is fully supported and handled automatically:

    Existing CA keys and device identity keys survive an upgrade. The certificate in LocalMachine\Root remains valid — no re-deployment of trust is required.

    Deploy the new MSI via Intune exactly as the initial install. The product UpgradeCode is the same across versions, so Intune will detect and replace the old version.

    Switching variants on upgrade: If you move a device from the default package to the standalone package (or vice versa), uninstall the current version first. Switching in-place is not supported because the two variants have different Product Codes.


    If the automatic install fails (e.g., policy blocks certutil, or the API started in non-elevated context), a convenience script is bundled with the installer:

    Run it from an elevated command prompt (or deploy via Intune PowerShell with SYSTEM context):

    Alternatively, use the raw certutil command:

    Or deploy via Intune → Trusted Certificate profile:

    1. Export the CA cert from the device: copy %LocalAppData%\T1CConnector\t1c-ca.pem → rename to .cer.

    2. Create a Trusted Certificate configuration profile in Intune.

    3. Upload the .cer file, set destination store to

    Note: If you use the Intune Trusted Certificate profile, each device will have a different CA certificate because the key pair is generated per-device. You cannot pre-generate a single CA and distribute it — the private key must stay on the device that owns it.


    Symptom
    Likely cause
    Fix

    The log contains timestamped entries for every cert operation with full certutil output, making it straightforward to diagnose trust store issues remotely via Intune's Collect diagnostics feature.

    Installation Sequence

  • Intune Deployment Requirements

  • Verifying a Successful Installation

  • Uninstallation

  • Upgrade (In-Place)

  • Fallback — Manual Root CA Installation

  • Troubleshooting

  • t1c-sandbox.exe

    Isolated card-reader process (lower privilege surface)

    t1c-api.exe

    t1c-reg.exe (optional)

    Device Registry daemon — registers device with the Distribution Service, syncs state across sessions

    t1c-api.exe — default package only; not present in the standalone variant

    Validity: 10 years (3 650 days)

  • Key Usage: keyCertSign, cRLSign (CA only — cannot be used as a leaf)

  • Basic Constraints: CA:true, critical

  • Subject Key Identifier present (required for Chrome chain validation)

  • Saves all four cert files (t1c-ca.pem, t1c-ca-key.pem, t1c-tls.pem, t1c-tls-key.pem) to the shared folder %LocalAppData%\T1CConnector\. If another package has already generated certs there, the existing valid cert is reused instead of generating a conflicting Root CA.

  • Issues a localhost TLS leaf certificate signed by the CA.

  • Installs the Root CA into the Windows machine trust store (LocalMachine\Root) using certutil -addstore Root.

  • No

    One-time dialog per user

    CurrentUser\Root
    modifications.

    Return codes

    0 = success

    Standard MSI exit code

    Computer certificate store — Root
    .
  • Assign to the target device group.

  • certutil -store Root "T1C Local Root CA" returns NOT_FOUND

    CA installed to CurrentUser\Root instead (non-elevated run)

    Re-install in System context, or use §10 fallback

    API not starting after install

    Startup registry key present but process not launched

    Log off and back on, or trigger via t1c-launch.exe --env prod --silent

    t1c-reg.exe not running (default package)

    Process crashed or not started

    Check %LocalAppData%\Trust1Connector\<date>.log; restart via t1c-launch.exe

    t1c-reg.exe missing from Program Files

    Standalone package deployed instead of default

    Re-deploy with the default (non-standalone) MSI if DS registration is required

    Uninstall leaves files in Program Files

    Processes were still running, locking files

    Run taskkill /F /IM t1c-api.exe /T before uninstall, then retry

    Uninstall leaves LocalAppData folder

    Old MSI package (pre-fix)

    Delete manually: rd /s /q "%LocalAppData%\Trust1Connector"

    signtool error during package build

    Windows SDK not on PATH

    Open a VS Developer Command Prompt, or update to latest package.bat (auto-detects SDK)

    Firefox still shows a warning

    Firefox NSS certutil not found

    Reinstall Firefox; the connector automatically registers with NSS on next start

    Contains t1c-reg.exe

    Intended environment

    Default

    Trust1Connector-x64-<ver>.msi

    Yes

    Shared / multi-user — Citrix, VDI, Terminal Server, RDS

    Standalone

    Trust1Connector-standalone-x64-<ver>.msi

    No

    Single dedicated device (workstation, kiosk)

    t1c-launch.exe

    Watchdog / launcher — reads config, starts the API

    Windows Run registry key (login) or Intune

    t1c-api.exe

    Main REST API. On first run: generates Root CA + TLS cert, installs CA to Windows trust store

    t1c-launch.exe

    LocalMachine\Root

    All users on the device

    Yes (SYSTEM/admin)

    None

    CurrentUser\Root

    Install behavior

    System

    Must run as SYSTEM to write to LocalMachine\Root without a UAC dialog

    Device restart behavior

    No specific action

    No reboot required

    OS

    Windows 10 1903 or later / Windows 11

    Architecture

    x64 (use x86 package only for 32-bit OS)

    Minimum disk

    ~150 MB

    Browser shows ERR_CERT_AUTHORITY_INVALID

    Root CA not in LocalMachine\Root

    Run §10 fallback or check §7 verification

    Browser shows ERR_CERT_AUTHORITY_INVALID after re-install

    Stale cert in store with old thumbprint

    certutil -delstore Root "T1C Local Root CA" then reinstall

    Table of Contents

    1. Architecture Overview

    2. Process Model

    3. Filesystem Layout

    4. Root CA — What It Is and Why It Matters

    Why a local Root CA is needed

    How the Root CA is generated

    Why machine-level trust is required for enterprise deployment

    Thumbprint verification

    5. Installation Sequence

    Key points for Intune

    6. Intune Deployment Requirements

    Package type

    Installation context — critical

    Install command

    Uninstall command

    Detection rules

    Applicability rules

    Group Policy / Intune policy dependencies

    7. Verifying a Successful Installation

    8. Uninstallation

    What the uninstaller does (in order)

    Via Intune

    Manual uninstall

    What is NOT removed

    9. Upgrade (In-Place)

    10. Fallback — Manual Root CA Installation

    11. Troubleshooting

    Log file location

    Win32 Content Prep Tool

    Only the logged-in user

    Browser / Web App
           │  HTTPS (localhost:51983)
           ▼
      t1c-api.exe          ← main REST API (Rust)
           │  spawns
           ▼
      t1c-sandbox.exe      ← sandboxed process for card reader I/O
    
      t1c-reg.exe          ← device registry daemon (default package only — not present in standalone)
    C:\Program Files\Trust1Connector\        ← managed by MSI (removed on uninstall)
        t1c-launch.exe
        t1c-api.exe
        t1c-sandbox.exe
        t1c-reg.exe                              ← device registry daemon (default package only; absent in standalone)
        t1cds.pub                               ← Directory Service public key
        t1c.cer / t1c.pem                       ← T1T wildcard cert (DS communication)
        install-ca.bat                          ← admin fallback script (see §10)
    
    C:\Users\<user>\AppData\Local\Trust1Connector\    ← runtime data (removed on uninstall)
        device.priv / device.pub / device_der.* ← device identity keys
        ds-txs.json                             ← Directory Service sync state
        *.log                                   ← application logs
    
    C:\Users\<user>\AppData\Local\T1CConnector\        ← shared cert store (all T1C packages)
        t1c-ca.pem                              ← Root CA certificate (PEM)
        t1c-ca-key.pem                          ← Root CA private key
        t1c-tls.pem                             ← localhost TLS leaf certificate
        t1c-tls-key.pem                         ← localhost TLS private key
    Get-ChildItem Cert:\LocalMachine\Root, Cert:\CurrentUser\Root |
      Where-Object { $_.GetCertHashString('SHA256') -eq '<thumbprint>' }
    msiexec /i Trust1Connector-x64-<version>.msi /quiet /norestart
    msiexec /i Trust1Connector-standalone-x64-<version>.msi /quiet /norestart
    msiexec /x {3D6B46ED-C178-4ED9-8F0E-FFCC13C6BE7D} /quiet /norestart
    HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{<ProductCode>}
    Key: DisplayName
    Value: Trust1Connector
    Path:  C:\Program Files\Trust1Connector\
    File:  t1c-api.exe
    $cert = Get-ChildItem Cert:\LocalMachine\Root |
            Where-Object { $_.Subject -like "*T1C Local Root CA*" }
    if ($cert) { Write-Output "Installed"; exit 0 }
    exit 1
    # 1. Root CA in machine trust store
    certutil -store Root "T1C Local Root CA"
    # Expected: certificate details printed; exit 0
    
    # 2. API process running
    Get-Process t1c-api -ErrorAction SilentlyContinue
    # Expected: process listed
    
    # 3. HTTPS endpoint responding
    try {
        $r = Invoke-WebRequest https://localhost:51983/v3/status -UseBasicParsing
        Write-Output "API OK: $($r.StatusCode)"
    } catch {
        Write-Output "API not reachable: $_"
    }
    
    # 4. CA file present on disk (shared cert folder)
    Test-Path "$env:LOCALAPPDATA\T1CConnector\t1c-ca.pem"
    
    # 5. Registry daemon running (default package only — skip for standalone)
    Get-Process t1c-reg -ErrorAction SilentlyContinue
    1. killApi        — taskkill /F on t1c-launch.exe, t1c-api.exe, t1c-sandbox.exe
                        + t1c-reg.exe (if present — default package only)
                        + 2 s pause for OS to release file handles
    2. CleanLocalAppData — rd /s /q %LocalAppData%\Trust1Connector\
                        (device keys, ds-txs.json, logs — package-specific files)
                        NOTE: %LocalAppData%\T1CConnector\ is NOT deleted (shared cert store)
    3. CA_RemoveRootCA — certutil -delstore Root "T1C Local Root CA"
    4. RemoveFiles    — removes C:\Program Files\Trust1Connector\
    5. Registry       — removes Run key and Uninstall entry
    msiexec /x Trust1Connector-x64-<version>.msi /quiet /norestart
    1. killApi        — kills all running T1C processes (same as uninstall step 1)
    2. Old version removed (file replacement only — LocalAppData is NOT deleted)
    3. New version files installed
    4. Service restarted
    5. API finds existing t1c-ca.pem in shared folder → reuses it (no cert regeneration, no re-trust needed)
    C:\Program Files\Trust1Connector\install-ca.bat
    :: Removes any stale copy and re-installs the Root CA from the shared cert folder
    C:\Program Files\Trust1Connector\install-ca.bat
    :: Remove stale entry (ignore error if not present)
    certutil -delstore Root "T1C Local Root CA" >nul 2>&1
    
    :: Install from the shared cert folder (written by the API on first run)
    certutil -addstore Root "%LocalAppData%\T1CConnector\t1c-ca.pem"
    %LocalAppData%\Trust1Connector\<date>.log

    Installation Profiles

    The different architectures supported by the Trust1Connector

    The Trust1Connector can be configured to comply with different installation scenario’s. This can be done when packaging the Trust1Connector, and is managed through setting the correct command-line arguments upon startup. To facilitate this, the Trust1Connector ships with a partner specific launcher which can be adapted to comply with different reqeusts.

    The Trust1Connector can be installed in different ways, depending on the requirements for a specific business context. By default the Trust1Connector uses the best approach for a device in an unknown context.

    The different setups describes below all share *the same codebase*. For each target the executables are exactly the same.

    We achieve this through command line parametrization of the executable. Updating the CLI parameters for the API or Registry modifies the behaviour of the runtime execution.

    This provides us with the following benefits:

    same code base, same binaries

  • change behaviour for a specific context

  • change behaviour at runtime

  • The installation profiles, as we tend to have many command line arguments, are encapsulated in a separate executable, this is called 't1c-launch'.

    The 't1c-launc' does the following:

    • validate the environment

    • validate prerequisites

    • start the connector executables

    • provide the correct CLI params, decided upon compilation time

    • provide an CLI param override mechanism, which is a pass-through for the overriden params to the executables (api/reg/sandbox)

    This document describes all achievable different scenario’s with pros and cons, depending on the business case.

    To understand how the Trust1Connector can be setup, it is good to have an overview of all components in the Trust1Connector eco system.

    Overall components

    Component

    Description

    Note

    T1C-SDK-JS

    An easy to use Javascript SDK for quick integration into partner web applications

    This is an optional component which can be used to ease and speed up the integration of the Trust1Connector into any web application. The SDK acts as an interface for the consuming web application and supports backwards compatibility

    REST Client

    A 3rd Party Rest client

    The Trust1Connector can be installed in ‘offline’ mode. This is the case when:

    • no internet connection is available

    • no centralised Distribution Service is available/wanted

    Following this approach, the installation base (devices with T1C installed) is managed from an software application distribution platform (version management, insights, …).

    The Trust1Connector is fully functional in an offline environment and contains all module logic in the installation footprint. The options explained here describes what are the possible modes for offline installations.

    Trusted browser and no PIN encryption between the browser and the connector application interface.

    Offline Desktop Mode

    Untrusted browser and PIN encryption enforced through the connector application interface.

    Offline Web-Encryption Desktop Mode

    The Shared Registry executable is introduced to resolve client address ports during initialization. The shared registry runs a single instance on one of the connected clients OR the host application.

    When the host is NOT running the shared registry, clients are dynamically checking if a registry is available. When a registry instance is not found, a random client launches a registry instance, untill the client becomes unavailable.

    Offline Shared Environment Mode

    In this mode the Distribution Service is used for one or both of the following categories of use cases:

    • connector client instance synchronization

    • central port resolution

    The former category denotes the device synchronization and management operational use cases.

    The lattter adds to the functionality by acting as a central registry, becoming a critical component during connector client instance initialization.

    In that scenario, connector instances are always bound to DS (Distribution Service); the DS is the centralized service handling the address port resolution for every client. A client will register it’s dynamically assigned port (from a configurable port range) at the DS. The DS resolves the address port for each web application trying to connect with it’s local client. The handshake is performed using an the web application consent flow.

    The DS is a central service collection all anonimized operation data for every linked connector instance.

    The DS serves the operational use cases:

    • demographic information

    • SSL and Device certificate rotation

    • client-demand log dispatching

    • CORS management

    • application application management

    Online Desktop Mode

    The communication from the web application towards the connector instance is secured and requires pre-requested JWT from the Distribution Service.

    The local connector instances enforces JWT validation prior to use case execution.

    Additional functionality for device key-rotation and application registry bindings are available in this context.

    Online Web-encryption Desktop Mode

    In this mode, DS communication is established but not blocking operationally once installed.

    PIN Encryption and shared registry is configured on the host or on the client dynamically (local election algorithm). The shared registry stores a list of agents, keeping track of agents-port correlation.

    The JWT authentication/validation on API is optional and configured during packaging.

    Online Shared Environment Mode with local host/client registry

    An extension on the profile above, is when an admin runs the 'registry' process on-startup, as a service user, in a shared environment. This means that the registry process will run always, and will not be changed throughout user sessions (especially when a user session gets invalidated, or stays acive even when de user has logged out.

    For shared environments, our recommendation is to start the registry process on a shared environment for all remote terminals/clients.

    The DS keeps track of the client address ports and resolves the port upon every new session between the browser and the local connector instance during initialisation. Additionally the public key for web application encryption is shared between the registry and the requestion client application.

    Online Shared Environment Mode with Central Registry

    The variants decribed hereafter differs in how the packager stores the files and executables during installation.

    In this mode, a user image is by default stateless and the connector is initialized upon every new user session.

    This implies that the connector instance will register upon startup, for every new user login.

    The user always starts with a clean installation when logged-in. This approach resembles with how Docker starts new images instances and can be used thus in a Docker image.

    This variant is called ‘split installer’ and splits the location of the executables during installation and the user session related configuration files (transaction info, consent, device certificates, logs, …).

    In this approach, the executables are provision in a predefined path (typically system program files or system folder).

    The user session related files are stored in a user specific folder location.

    Overview

    Overall Components

    Offline Modes

    Offline Desktop Mode

    Offline Web-encryption Desktop Mode

    Offline Shared Environment Mode

    Online Modes

    Online Desktop Mode

    Online Web-encryption Desktop Mode

    Online Shared Environment Mode with Local Host/Client Registry

    Online Shared Environment Mode with Central Registry

    Other Variants

    Shared Environments Share User Image

    Shared Environments Share Binary Folder

    Core Service

    Introduction

    The Trust1Connector core services address communication functionality with local devices. The Trust1Connector core exposes 2 main interfaces:

    • interface for web/native applications using JavaScrip/Typescript

    • REST API as a new approach and to incorporate the Trust1Connector as a microservice in the application architecture

    In this guide, we target only the use of Trust1Connector's core interface for web/native applications. The T1C-SDK-JS exposes protected resources for administration and consumer usage.

    The JavaScript library must be in order to access the all resource.

    Consumer resources are typically used from an application perspective:

    • Get pub-key certificate

    • Get version

    • Get Information (operating system, runtime, user context, variable configuration)

    Executing these functionality is explained further.

    The Trust1Connector functionalities are about secured communication with device hardware. The document highlights communication with smart card readers - contact and contact-less. Other hardware devices can be enabled or integrated as well in the solution. Some of the already are, for example printer drivers, signature tablet drivers, ...

    After you've you can execute the rest of the Trust1Connector's functionality, for example listing the readers and fetching information from a specific smart card.

    Returns a list of available card readers. Multiple readers can be connected. Each reader is identified by a unique reader_id.

    The response will contains a list of card readers:

    When multiple readers are attached to a device, the response will show all connected card readers:

    Important to notice:

    • The response adds a card-element when a card is inserted into the card reader.

    • The response contains card-reader pin-pad capabilities

    As mentioned in the List card-readers, when a smart-card is inserted/detected, the reader will contain the cart-type based on the ATR. The ATR (Anwser To Reset), is the response from any smart-card when powered, and defines the card type. The Trust1Connector recognized more than 3k smart-card types.

    Possibility to exclude certain readers based on their name

    As mentioned in the List card-readers, when a card-reader has pin-pad capabilities, this will be mentioned in the response (notice the pinpadproperty):

    The following example is the response for List card-readers on a device with 4 different card-readers attached:

    In the above example you notice that 4 card-readers are connected. Each card-reader receives his temporary id which can be used for other functions where a card-reader id is needed. This method can be requested in order to list all available card-readers, and optional cards-inserted. Each card-reader has a vendor provided name, which is retrieved from the card-reader itself. An additional property pinpad, a boolean value, denotes if the card-reader has pin-pad capabilities. A pin-pad is a card-reader, most of the times with its own display and key-pad. From a security perspective, it's considered best practice to use as much as possible pin-pad capabilities of a pin-pad card-reader. When a reader has a smart-card inserted (contact interface) or detected (contactless interface), the card type will be resolved by the GCL in order to respond with a meaningful type. In the above examples you see that; one card-reader has a Belgian eID card; another card-reader has a MisterCash or VISA Card available for interaction.

    The readers returned, are the card-readers with a card available. The card-readers where no card is presented, are ignored.

    Returns a list of available card readers with a smart card inserted. Multiple readers can be connected with multiple smart cards inserted. Each reader is identified by a unique reader_id and contains information about a connected smart card. A smart card is of a certain type. The Trust1Connector detects the type of the smart card and returns this information in the JSON response.

    Response:

    To retrieve the version of the Javascript SDK you can use the version function available in the CoreService

    You can follow the example below to retrieve the version number

    The ouput in the log of the code above should look like the following

    via the getDevicePublicKey endpoint you're able to fetch the public key information of the device. This requires an authenticated client to be able to access this endpoint.

    This endpoint is used in the library to encrypt pin, puk and pace information so that it is not exposed in the network logs of the browser.

    Encryption of pin, puk and pace is only possible when the Trust1Connector is registered via a DS and has a valid device key-pair. The SDK will automatically switch to send the pin, puk or pace info in clear text if its not able to encrypt. The Trust1Connector API will also detect if it has no valid device key-pair it will not try to decrypt the incoming pin, puk or pace information.

    Via the pushLogs function you can trigger the Trust1Connector to send out the log files towards the Distribution service.

    Any REST client can be used to address the Trust1Connector use cases directly from your consuming application. Applications can be native desktop applications or web applications in any technology

    T1C-Sandbox

    A secured Sandbox for smart card APDU execution, exposing a gRPC interface

    The Sandbox can be used directly for certain applications, but it’s main goal is to isolate the APDU interactions towards smart cards, and card readers (contact or contactless)

    T1C-Rust-API

    An OpenAPI REST interface, acting as an addressable microservice.

    The local REST Service, installed on the local device, serving the functionality used directly from consuming applications or from the T1C-SDK-JS. The OpenAPI YAML is published and can be used to generate a REST client in any technology

    T1C-Registry [Decentralised]

    An optional Local Registry for multi-host or shared environments.

    It is required when using Trust1Connector on a shared machine with multiple users. The component is optional, and a central registry can be used as well. The integrating party must choose whether to opt for a local dynamic registry or a central Distribution Service Registry

    T1C-Registry [Centralised]

    An optional Centralised Registry for multi-host or shared environments. The service can only be used when a Distribution Service is provided in the solution architecture.

    It is required when using Trust1Connector on a shared machine with multiple users. The component is optional, and a local dynamic registry can be used as well. The integration party must choose whether to opt for a decentralised or centralised approach. When choosing a centralised approach, a Distribution Service setup is needed.

    T1C-DS

    The Trust1Connector Distribution Server is a central management service for the T1C.

    The DS is serving use cases for version management, demographic information, key rotation, additional security protection, dynamic CORS, application management and more

    Virtual Reader

    The remote loading implementation for a backend smart card service

    The virtual card reader acts as a remote smart card reader, able to communicate with any card on a remote client enabling HSMs (High security modules), central card management systems, smart card personalisation use cases and more

    API Gateway

    An optional API gateway introduced when using the T1C-DS for security policy enforcement

    As the T1C-DS acts as a REST microservice, additional security measurement must be taken into account. The API gateway implements different security policies applied on:

    • Device to DS communication

    • Application to DS communication

    List card-readers (with active card)
  • Get card-reader

  • List card-readers (with active cards)

  • List card-readers (with or without active card)

  • Trigger a push of the log files towards the DS

  • Consumer resources

    Core Functionalities

    List card readers

    Card Inserted

    Excluded by name

    This exclude readers will search for the term in the reader names and exclude those that match with the term

    Pin-Pad Capabilities

    List Card-Readers - Explained Example

    Get card reader with card inserted

    Get the Javascript SDK version

    Get device public key

    Push log files

    Core interface

    initialized correctly
    initialized the Trust1Connector
    T1CSdk.T1CClient.initialize(config).then(res => {
        var coreService = res.core();
        core.readers(callback);
    }, err => {
        console.error(err);
    });)
    {
      "success": true,
      "data": [
        {
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false,
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card (eID)"
            ],
            "module": "beid"
          }
        }
      ]
    }
    {
      "data": [
        {
          "id": "ec3109c84ee9eeb5",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(2)",
          "pinpad": false
        },
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        },
        {
          "id": "c8d31f8fed44d952",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(1)",
          "pinpad": false
        }
      ],
      "success": true
    }
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    core.readersExcludeByName("Bit4id", callback);
    {
      "data": [
      ],
      "success": true
    }
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    {
      "data": [
        {
          "id": "ec3109c84ee9eeb5",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(2)",
          "pinpad": false
        },
        {
          "card": {
            "atr": "3B67000000000000009000",
            "description": [
              "MisterCash & Proton card",
              "VISA Card (emitted by Bank Card Company - Belgium)"
            ]
          },
          "id": "e5863fcc71478871",
          "name": "Gemalto Ezio Shield Secure Channel",
          "pinpad": true
        },
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [
              "Belgium Electronic ID card"
            ]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        },
        {
          "id": "c8d31f8fed44d952",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(1)",
          "pinpad": false
        }
      ],
      "success": true
    }
    T1CClient.initialize(config).then(client => {
        var coreService = client.core();
        core.readersCardAvailable(callback);
    }, err => {
        console.error(err);
    });
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": []
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    T1CSdk.T1CClient.initialize(config).then(client => {
        var coreService = client.core();
        core.version().then(version => {
            console.log(version)
        });
    }, err => {
        console.error(err);
    });
    3.5.3
    export interface AbstractCore {
      getImplicitConsent(codeWord: string, durationInDays?: number, callback?: (error?: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>;
      validateConsent(consent: string, callback?: (error?: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>;
      updateJWT(jwt: string, callback?: (error: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>
      info(callback?: (error: T1CLibException, data: InfoResponse) => void): void | Promise<InfoResponse>;
      reader(reader_id: string, callback?: (error: T1CLibException, data: SingleReaderResponse) => void): Promise<SingleReaderResponse>;
      readers(callback?: (error: T1CLibException, data: CardReadersResponse) => void): Promise<CardReadersResponse>;
      readersCardAvailable(callback?: (error: T1CLibException, data: CardReadersResponse) => void): Promise<CardReadersResponse>;
      readersExcludedByName(name: string, callback?: (error: T1CLibException, data: CardReadersResponse) => void): Promise<CardReadersResponse>;
      readersCardsUnavailable(callback?: (error: T1CLibException, data: CardReadersResponse) => void): Promise<CardReadersResponse>;
      getUrl(): string;
      getDevicePublicKey(): void;
      dsCorsSync(): Promise<boolean>;
      pushLogs(): Promise<boolean>;
      version(): Promise<string>;
    }

    Downloading latest Trust1Connector

    Downloading Trust1Connector

    The T1C JS SDK no longer has a method to download the T1C installer.

    Instead, the T1C installer can be downloaded by navigating the client browser to the /v3_5/downloads/installer endpoint of the Distribution Service (e.g. https://acc-ds.t1t.io/v3_5/downloads/installer). The Distribution Service will analyse the User-Agent header and automatically initiate the download of an OS-appropriate installer of the latest configured version. The user agent string parsing is considered "best-effort"; as they can vary wildly depending OS and browser software.

    Alternatively, you can also initiate the download of a T1C installer with the following endpoints:

    1. /v3_5/downloads/installers/{{OS}}: This endpoint allows you to specify the OS for which you wish to obtain an installer. The possible values are win32, win64, unix, macos macosarm.

    2. /v3_5/downloads/installers/{{OS}}/versions/{{version}}: This endpoint allows you to download a specific version of a T1C installer for a specific OS.

    For MacOS there are currently 2 supported architectures:

    • ARM64 (M1, ...)

    • Intel x86_64

    Currently, browsers etc do not display which architecture you're running. So in order to provide download links to the users you need to provide them with the option to download any of the 2 architectures. The user needs to decide which platform he is running.

    From the DS you can get both links with the following URL's (Production DS is used in the example);

    After this, you can provide the user with the choice of which one they want to download. Below you can see an example of how Google does this with their Browser, Google Chrome.

    Here you can clearly see they provide two versions, with a recommendation on Intel because the majority of the users still run Intel Apple devices

    Below you can find a list of Distribuction services available from Trust1Team. If you are integrating with a 3rd party that uses the Trust1Connector you can contact them for information regarding the Distribution services.

    Via the Distribution service you can fetch the latest available version. This can be done via the call

    This will return all information needed from the latest version, for example our latest version at this point returns:

    You can check the boolean values mandatory recommended and allowed to determine a pop-up for example, so that the user can download and use this Trust1Connector.

    You can also retrieve the same information for a specific version. This endpoint returns the same response type as the latest version call:

    Example screenshot below of our demo-application (rmc.t1t.io)

    Below you can find an example of how an version check can be implemented in your front-end application.

    # Intel x86_64
    https://ds.t1t.io/v3_5/downloads/installers/macos
    
    # ARM64
    https://ds.t1t.io/v3_5/downloads/installers/macosarm

    Environment

    DS url

    Acceptance

    https://acc-ds.t1t.io

    Production

    https://ds.t1t.io

    curl --location --request GET 'https://acc-ds.t1t.io/v3_5/versions/latest' \
    --header 'Authorization: Bearer eyJh...BCr8Q'
    {
    	"success": true,
    	"data": {
    		"id": "3.6.0",
    		"createdOn": "2022-03-21T07:47:48.590425Z",
    		"updatedOn": "2022-05-30T10:46:36.532283Z",
    		"recommended": false,
    		"mandatory": false,
    		"allowed": true,
    		"visible": true,
    		"uris": [
    			{
    				"os": "MACOSARM",
    				"uri": "https://storage.googleapis.com/t1c-dependen....e/trust1team/Trust1Connector-arm.dmg"
    			},
    			{
    				"os": "UNIX",
    				"uri": "https://storage.googleapis.com/t1c-depend....trust1team/trust1connector.deb"
    			},
    			{
    				"os": "MACOS",
    				"uri": "https://storage.googleapis.com/t1c-dep....Trust1Connector Acceptance-x86.dmg"
    			},
    			{
    				"os": "WIN64",
    				"uri": "https://storage.googleapis.com/t1c-depe....t1Connector-Acceptance-x64.msi"
    			},
    			{
    				"os": "WIN32",
    				"uri": "https://storage.googleapis.com/t1c-dependenci...ust1Connector-Acceptance-x86.msi"
    			}
    		],
    		"installationApiKey": "6257cbe3-e25a-.....-9fb9-02ad17d1f193"
    	}
    }
    curl --location --request GET 'https://acc-ds.t1t.io/v3_5/versions/3.6.0' \
    --header 'Authorization: Bearer eyJh...BCr8Q'

    If using the generic endpoint 3_5/downloads/installer

    The automatic user-agent detection also does not differentiate between ARM/M1 and Intel Mac devices

    Differentiate between MacOS architectures

    Distribution services

    Example upgrade flow

    Information below is an example. If the integrator pleases he can alter the flow to their business use-case

    In the call above, you can substitute 3.6.0 for the desired version ID

    Quick-Migration Guide (v2 -> v3)

    Introduction

    When you already have a V2 integrated this page will provide you with some easy steps to quickly migrate to the V3 of the Trust1Connector. Migration from the v2 to the v3 of the Trust1Connector can be done in 2 ways;

    1. Integration of the API

    2. Integration via the deprecated Javascript SDK

    Both are viable integrations. When integrating via the API you have more control over the functionality and the dependencies used.

    Update a v2 application to v3

    For updating your web application first of all you need to use the new Javascript SDK. After this there are some differences in using the SDK from the v2.

    The configuration from the v2 has changed, we simplified this.

    The v2 had the following configuration options;

    With the v3 this is significantly simplified to the following;

    After you've created your configuration object you can do the initialisation of the Trust1Connector SDK. This has largely remained the same except for the error codes.

    V2 example:

    V3 example;

    For more information regarding initialization we suggest the

    is the port where the webserver is listening on, in the v2 this is 10443 but in the v3 by default(T1T) this is 51983

    t1cProxyPort

    This value represents the port where the Proxy webserver is listening on. By default this is 51983 (obsolete)

    t1cProxyUrl

    Similar to the api url this is the URL where the proxy used in shared environment is running on. This is by default the same as the API url (obsolete)

    applicationDomain

    Host of the web application the Trust1Connector is being used on. This property is used to make sure no collisions can happen

    apiKey

    /

    gwJwt

    jwt

    JWT token used for authentication of the web application towards the Trust1Connector. This must be retrieved from the web applications backend

    tokenExchangeContextPath

    /

    ocvContextPath

    /

    dsContextPath

    /

    in v2 this was the context path for the DS based on the gwOrProxyUrl

    dsFileContextPath

    /

    pkcs11Config

    /

    agentPort

    /

    implicitDownload

    /

    forceHardwarePinpad

    /

    sessionTimeout

    /

    consentDuration

    /

    syncManaged

    /

    osPinDialog

    /

    boolean which depicts the default os pin dialog value

    containerDownloadTimeout

    /

    localTestMode

    /

    lang

    /

    providedContainers

    /

    export class GCLConfigOptions {
        constructor(public gclUrl?: string,
                    public gwOrProxyUrl?: string,
                    public apiKey?: string,
                    public gwJwt?: string,
                    public tokenExchangeContextPath?: string,
                    public ocvContextPath?: string,
                    public dsContextPath?: string,
                    public dsFileContextPath?: string,
                    public pkcs11Config?: Pkcs11ModuleConfig,
                    public agentPort?: number,
                    public implicitDownload?: boolean,
                    public forceHardwarePinpad?: boolean,
                    public sessionTimeout?: number,
                    public consentDuration?: number,
                    public consentTimeout?: number,
                    public syncManaged?: boolean,
                    public osPinDialog?: boolean,
                    public containerDownloadTimeout?: number,
                    public localTestMode?: boolean,
                    public lang?: string,
                    public providedContainers?: T1CContainerid[]) {
        }
    }
    class T1CConfigOptions {
      constructor(
        public t1cApiUrl?: string,
        public t1cApiPort?: string,
        public t1cProxyUrl?: string, // deprecated
        public t1cProxyPort?: string, // deprecated
        public jwt?: string,
        public applicationDomain?: string, // "rmc.t1t.be"
      ) {}
    }

    V2 config option

    V3 config option

    Description

    gclUrl / gwOrProxyUrl

    t1cApiUrl

    in the V2 this was https://localhost:10443 while in the V3 this will be https://t1c.t1t.io (for T1T)

    config = new GCLLib.GCLConfig(configoptions);
        GCLLib.GCLClient.initialize(config).then(res => {
            client = res;
            core = client.core();
            console.log("GCLClient: ", res)
        }, err => {
            console.log("GCL error:", err)
        })
    config = new T1CSdk.T1CConfig(configoptions);
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        console.log("Client config: ", client.localConfig)
        core = client.core();
    
    }, err => {
        errorHandler(err);
    });

    Configuration

    Initialisation

    Initialize page

    t1cApiPort

    Module/container setup

    Introduction

    This document will describe how you can set up your desired module or generic module for using the functionalities that each module have. This ofcourse requires you to succesfully initialized the Trust1Connector via initialize or authenticated client and have a valid reader to contact

    Initialize your module

    When the user has selected his desired reader to use we can continue to initialize the module to use. This requires at least the readerID to properly initialize.

    Some modules like the LuxID module require you to also add a additional pin and pinType for example, this will also need to be provided in the module initialization.

    To initialize a module we first need the client as described in the introduction, here's a quick happy flow of how to retrieve a T1CClient

    When we have the T1CClient we can use this to choose our module. We can also use the generic interface if we want.

    Below is an example of how to iniailize the Belgian EID module. This is a specific module that has all the functionalities for the Belgian EID card. You can see we use the client to fetch an instance of the beid module which we can further use to execute any functionality exposed on the beid module.

    now we can use this to for example fetch all the available token data;

    Ofcourse we can also use the generic interface which has all the functions exposed that you can use for all the modules.

    This will require you to always provide the module when you call any of its functions. Because it still needs to know which commands it needs to send to the card/token.

    When we now want to execute a getAllData for beid we would call it like this;

    To initialise a generic payment module its very similar to the token version but the available functions will differ.

    When we now want to execute a readData for emv we would call it like this;

    Below you can find an overview of the generic interfaces. This shows what functions are available on both. If you want more information about a specific token/module you need to go to their respecitve pages which will explain more in detail what you can do with them.

    Below is a list of the available modules;

    • generic

    • paymentGeneric

    • fileex

    these are the exposed functions available on the T1CClient to initialize a module

    Authenticated client

    The Trust1Connector API requires a valid JWT token to be provided in the Authorization header. This JWT token can be retrieved by asking the Distribution Service to generate a token for a specific API-key. It is important that this API-key is not exposed in the front-end application as this is a security violation.

    When you've received a valid JWT token from the DS you can provide this into the configuration object when initialising the Trust1Connector JS client.

    When using the Trust1Connector Javascript SDK the Authorization header is automatically populated with the JWT provided while initialising.

    When the Token has expired there is a function which you can call to provide a new token and which will in turn return an updated client to be used.

    Mac OSX

    Installation Guide

    Initially when starting the application, and no Trust1Connector has been installed the following layout will be presented:

    The Home Page allows the user to download the Trust1Connector or view which version is currently installed. Although the connector can determine which operating system is running the browser, the page shows all possible downloads. Available installers are provided for:

    • Windows 32/64 bit (LTS)

    Consent
    rawprint
  • beid

  • remoteloading

  • emv

  • crelan

  • aventra

  • oberthur

  • idemia

  • luxeid

  • wacom

  • diplad

  • certigna

  • certinomis

  • dnie

  • safenet

  • eherkenning

  • jcop

  • airbus

  • luxtrust

  • camerfirma

  • chambersign

  • the reader_id is the identifier which can be retrieved from the readers functionality

    Base module initialization

    Generic

    Generic Token

    Generic is split up in 2 different generic modules. This is because the payment modules differ to much from the regular tokens.

    Generic Payment

    Interfaces

    Generic Token interface

    Generic Payment interface

    Available modules

    Functions

    Retrieving a valid JWT token happens via the DS. When passing a valid API-key to header of the endpoint
    {{ds-url}}/v3/tokens/application
    (GET) you wil in turn receive a valid JWT token.

    Example response

    A JWT token is only valid for a certain period. After this period the API will return an error. At this point you need to request a new JWT token to be able to communicate with the API.

    In the T1C JS SDK there is a function which you can use to re-initalise the client with a new valid JWT token. This should be done when you receive a 104025 error-code which means you do not have a valid JWT

    The updateJWT function can be found in the Core service. After initialising you can retrieve the core as follows:

    The function's interface is as follows;

    This function returns an updated client which you can continue to use for your desired use-cases.

    Environment

    DS url

    Acceptance

    https://acc-ds.t1t.io

    Production

    https://ds.t1t.io

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Retrieving a JWT token

    Refresh JWT token

    Refreshing the JWT token can only be done after a first successfull initialisation of the Trust1Connector. This means the Trust1Connector has to be initialised with a valid configuration the first time. When the token expires after first successfull initialisation you can use the refreshJWT function described below

    Distribution services

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    const beid = client.beid(reader_id);
    beid.allData(filters).then(...).catch(...)
    // pin and pin_type are needed for luxid
    const generic = client.generic(reader_id, pin, pin_type)
    generic.allData('beid', filters).then(...).catch(...)
    const generic = client.paymentGeneric(reader_id)
    generic.readData('emv').then(...).catch(...)
    export interface AbstractEidGeneric {
      allData(module: string, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
      allCerts(module: string, parseCerts?: boolean,  filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      biometric(module: string, callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
      tokenData(module: string, callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
      address(module: string, callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
      picture(module: string, callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
      rootCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      intermediateCertificates(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      encryptionCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      issuerCertificate(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(module: string, parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      intermediateCertificatesExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      encryptionCertificateExtended(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      issuerCertificateExtended(module: string, parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(module: string, body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(module: string, body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(module: string, body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(module: string, callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(module: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    export interface AbstractPaymentGeneric {
      readApplicationData(module: string, callback?: (error: T1CLibException, data: PaymentReadApplicationDataResponse) => void): Promise<PaymentReadApplicationDataResponse>;
      readData(module: string, callback?: (error: T1CLibException, data: PaymentReadDataResponse) => void): Promise<PaymentReadDataResponse>;
    
      allCerts(module: string, aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: PaymentAllCertsResponse | TokenAllCertsExtendedResponse) => void): Promise<PaymentAllCertsResponse | TokenAllCertsExtendedResponse>;
      issuerPublicCertificate(module: string, aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
      iccPublicCertificate(module: string, aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
    
      allCertsExtended(module: string, aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      issuerPublicCertificateExtended(module: string, aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      iccPublicCertificateExtended(module: string, aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(module: string, body: PaymentVerifyPinData, callback?: (error: T1CLibException, data: PaymentVerifyPinResponse) => void): Promise<PaymentVerifyPinResponse>;
      resetBulkPin(module: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
      sign(module: string, body: PaymentSignData, bulk?: boolean, callback?: (error: T1CLibException, data: PaymentSignResponse) => void): Promise<PaymentSignResponse>;
    }
    public generic = (reader_id: string, pin?: string, pinType?: PinType): AbstractEidGeneric => {
        return this.moduleFactory.createEidGeneric(reader_id, pin, pinType)
    };
    
    public paymentGeneric = (reader_id: string): AbstractPaymentGeneric => {
        return this.moduleFactory.createPaymentGeneric(reader_id)
    };
    
    public fileex = (): AbstractFileExchange => {
        return this.moduleFactory.createFileExchange()
    };
    
    public rawprint = (): AbstractRawPrint => {
        return this.moduleFactory.createRawPrint()
    };
    
    public beid = (reader_id: string): AbstractEidBE => {
        return this.moduleFactory.createEidBE(reader_id)
    };
    
    public remoteloading = (reader_id: string): AbstractRemoteLoading => {
        return this.moduleFactory.createRemoteLoading(reader_id)
    };
    
    public emv = (reader_id: string): AbstractEmv => {
        return this.moduleFactory.createEmv(reader_id)
    };
    
    public crelan = (reader_id: string): AbstractCrelan => {
        return this.moduleFactory.createCrelan(reader_id)
    };
    
    // get instance for Aventra
    public aventra = (reader_id: string): AbstractAventra => {
        return this.moduleFactory.createAventra(reader_id);
    }
    
    // get instance for Oberthur
    public oberthur = (reader_id: string): AbstractOberthur73 => {
        return this.moduleFactory.createOberthur(reader_id);
    }
    
    // get instance for Oberthur
    public idemia = (reader_id: string): AbstractIdemia => {
        return this.moduleFactory.createIdemia(reader_id);
    }
    
    public luxeid = (reader_id: string, pin: string, pin_type: PinType): AbstractEidLux => {
        return this.moduleFactory.createEidLUX(reader_id, pin, pin_type);
    }
    
    public wacom = (): AbstractWacom => {
        return this.moduleFactory.createWacom();
    }
    
    public diplad = (reader_id: string): AbstractEidDiplad => {
        return this.moduleFactory.createEidDiplad(reader_id);
    }
    
    public certigna = (reader_id: string): AbstractCertigna => {
        return this.moduleFactory.createCertigna(reader_id);
    }
    
    public certinomis = (reader_id: string): AbstractCertinomis => {
        return this.moduleFactory.createCertinomis(reader_id);
    }
    
    public dnie = (reader_id: string): AbstractDNIe => {
        return this.moduleFactory.createDNIe(reader_id);
    }
    
    public safenet = (reader_id: string): AbstractSafenet => {
        return this.moduleFactory.createSafenet(reader_id);
    }
    
    public eherkenning = (reader_id: string): AbstractEherkenning => {
        return this.moduleFactory.createEherkenning(reader_id);
    }
    
    public jcop = (reader_id: string): AbstractJcop => {
        return this.moduleFactory.createJcop(reader_id);
    }
    
    public airbus = (reader_id: string): AbstractAirbus => {
        return this.moduleFactory.createAirbus(reader_id);
    }
    
    public luxtrust = (reader_id: string): AbstractLuxTrust => {
        return this.moduleFactory.createLuxTrust(reader_id);
    }
    
    public camerfirma = (reader_id: string): AbstractCamerfirma => {
        return this.moduleFactory.createCamerfirma(reader_id);
    }
    
    public chambersign = (reader_id: string): AbstractChambersign => {
        return this.moduleFactory.createChambersign(reader_id);
    }
    // Config object definition
    export class T1CConfigOptions {
      constructor(
        public t1cApiUrl?: string,
        public t1cApiPort?: string,
        public t1cProxyUrl?: string,
        public t1cProxyPort?: string,
        public jwt?: string
      ) {}
    }
    
    
    
    // example
    const configoptions = new T1CSdk.T1CConfigOptions(
      environment.t1cApiUrl,
      environment.t1cApiPort,
      environment.t1cProxyUrl,
      environment.t1cProxyPort,
      environment.jwt
    );
    config = new T1CSdk.T1CConfig(configoptions);
    curl --location --request GET 'https://acc-ds.t1t.io/v3_5/tokens/application' \
    --header 'apikey: your-api-key'
    {
        "success": true,
        "data": "eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJ0MWNkcy1hcHAiLCJzdWIiOiJkZXZlbG9wbWVudCIsImV4cCI6MTU5OTA1MTExMywiaWF0IjoxNTk5MDQ5OTEzLCJuYmYiOjE1OTkwNDk5MDh9.LE_AdYv9PWxqSRm6-lkV_3TxInCqbf_hTwHFKCFfYwkuzex6AMkeW6FaVCOxu-EBU158S2g70i4VBpeT2TAr0IoOyjK-nalvVG5aB9MwidZMtiPlidcUfsDhsyhbhwqlhI2dzB5J5KsBmvZwpoG-Pg2koUSidruixg3SxRrCMotBRlRNKItnYgfs6_wvd_OOLXs2OlufYOD876MWcJymBK48wf9ESQ50clR3zwPAQsNnXFq2Augk0gOlCgWO1--WgaFeMnBF28b7genZXIkwZCfT82nRYtiOs0zLK2WtyireTHDgjIZif4nX8pggE7t_63Hbv8wCvv8_Mg2PfdhCMQ"
    }
    const configoptions = new T1CSdk.T1CConfigOptions(
      environment.t1cApiUrl,
      environment.t1cApiPort,
      environment.t1cProxyUrl,
      environment.t1cProxyPort,
      environment.jwt
    );
    config = new T1CSdk.T1CConfig(configoptions);
    
    T1CSdk.T1CClient.initialize(config).then(res => {
            client = res;
            console.log("Client config: ", client.localConfig)
            core = client.core();
        }, err => {});
    updateJWT(jwt: string, callback?: (error: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>
    core.updateJWT("jwt").then(client => {}, error => {});
    Mac Intel/ARM (LTS)
  • Linux (Ubuntu/Debian or other upon request)

  • After the downloaded, the signed package can be installed on your system. The connector has been build to have a small footprint. After a successful installation, the page must be refreshed. The application has been build to avoid explicit polling of readers prior to the installation.

    The installation wizard will be started when the downloaded installer is executed:

    Installation Wizard Starts

    Installation Wizard Finished

    The Trust1Connector SDK determines the targetted operating system and provides the user with a download link.

    Installation

    Belgian eID

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The Belgian eID container facilitates communication with card readers with inserted Belgian eID smart card. The T1C-JS client library provides function to communicate with the smart card and facilitates integration into a web or native application. This document describes the functionality provided by the Belgian eID container on the T1C

    Interface

    export interface AbstractEidBE {
      allData(filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
      biometric(callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
      tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
      tokenVersion(callback?: (error: T1CLibException, data: TokenVersionResponse) => void): Promise<TokenVersionResponse> 
      address(callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
      picture(callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
      allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      intermediateCertificates(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      intermediateCertificatesExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Get Belgian eID container object

    Initialise a Trust1Connector client:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Get the Belgian eID container service:

    var beid = client.beid(reader_id);

    Call a function for the Belgian eID container:

    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    beid.biometric(callback);

    Obtain the Reader-ID

    The constructor for the Belgian eID expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:

    This function call returns:

    We notice that a card object is available in the response in the context of a detected reader. The reader in the example above is Bit4id miniLector, has no pin-pad capabilities, and there is a card detected with given ATR and description "Belgian eID Card". An ATR (Answer To Reset) identifies the type of a smart-card. The reader, has a unique ID, reader_id; this reader_id must be used in order to request functionalities for the Belgian eID card. This must be done upon instantiation of the Belgian eID container:

    All methods for beid will use the selected reader - identified by the reader_id.

    The card holder is the person identified using the Belgian eID card. It's important to note that all data must be validated in your backend. Data validation can be done using the appropriate certificate (public key).

    Contains all card holder related data, excluding the card holder address and photo. The service can be called:

    An example callback:

    Response:

    Contains the card holder's address. The service can be called:

    Response:

    Contains the card holder's picture stored on the smart card. The service can be called:

    Response:

    The token info contains generic information about the card and it's capabilities. This information includes the serial number, file types for object directory files, algorithms implemented on the card, etc.

    Response can either be a BaseTokenInfo or a PKCS11TokenInfo object. Depending if its a pkcs11 token or not

    The token version function is a specific function for Belgian eID. It will return the version of the card in the reader.

    This can either be 1.7 or 1.8

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'citizen CA certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not. The service can be called:

    Response:

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the citizen certificate stored on the smart card. The 'citizen certificate' is used to sign the 'authentication certificate' and the 'non-repudiation certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the biometric data

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    As the Beid module incorperates Beid 1.7 and 1.8 there is a difference in the algorithms being used. In 1.7 we have the following;

    • md5

    • sha1

    • sha256

    For beid 1.8 we have;

    • sha2_256

    • sha2_384

    • sha2_512

    As we've noticed most integrators use sha256 and to make sure current integrations do not break we have made the Trust1Connector to map sha256 to sha3_256 for beid 1.8. Ofcourse if you want to use a specifc supported algorithm you can still select them.

    By default the 1.7 will fall back to sha256 and 1.8 to sha3_256 if an incompatible algorithm is passed to the function.

    The tables below explain which algorithm will be used when providing a certain algorithm value in the function;

    Data can be signed using the Belgian eID smart card. To do so, the T1C facilitates in:

    • Retrieving the certificate chain (citizen-certificate, root-certificate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When signing with a crelan card reader, it is additionally possible to optionally specify a transaction ID and the language. If the card reader is not a Crelan reader, these values will be ignored. This applies to all signing methods described below.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    In order to calculate a hash from the data to sign, you need to know the algorithm you will use in order to sign.

    You can use the following online tool to calculate the SHA256:

    Hexadecimal result:

    Notice that the length of the SHA256 is always the same. Now we need to convert the hexadecimal string to a base64-encoded string, another online tool can be used for this example:

    Base64-encoded result:

    Now we can sign the data:

    Result:

    Note: If you want to convert a binary signed hash to HEX (for development) you can use for example an online hexdump tool:

    Digest Alg
    Digest Example

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    In order to inform a user upon the PIN retries left, the Belgian eID doesn't provide a request to retrieve this information. After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

    Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status.

    For more information about the error codes you can check the

    As the Beid module incorperates Beid 1.7 and 1.8 there is a difference in the algorithms being used. In 1.7 we have the following;

    • md5

    • sha1

    • sha256

    For beid 1.8 we have;

    • sha2_256

    • sha2_384

    • sha2_512

    As we've noticed most integrators use sha256 and to make sure current integrations do not break we have made the Trust1Connector to map sha256 to sha3_256 for beid 1.8. Ofcourse if you want to use a specifc supported algorithm you can still select them.

    By default the 1.7 will fall back to sha256 and 1.8 to sha3_256 if an incompatible algorithm is passed to the function.

    The tables below explain which algorithm will be used when providing a certain algorithm value in the function;

    The T1C is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

      Response:

    Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    v3.8.10

    Trust1Connector — Release Notes v3.8.10

    Release date: June 2026 Packages: Default Trust1Connector Branches: (API) · (Installers)


    Highlights

    Area
    What changed

    Localhost SSL

    Full self-signed CA + TLS leaf certificate lifecycle built into the API, trusted by all browsers without any user action


    The API now generates, manages, and renews its own TLS infrastructure on every device without any pre-provisioned certificate:

    • Per-device Root CA generated on first startup with a 4096-bit RSA key pair. The CA includes correct SubjectKeyIdentifier and AuthorityKeyIdentifier extensions, making it accepted by all modern browsers and OpenSSL chains.

    • Leaf certificate (TLS server cert) generated from the Root CA with a random 128-bit serial number, eliminating the SEC_ERROR_REUSED_ISSUER_AND_SERIAL error in Firefox.

    All four certificate files are now stored in a single shared folder that every T1C package on the device reads and writes:

    • If a valid Root CA already exists in this folder (generated by another T1C package), the API reuses it instead of generating a conflicting second CA.

    • The shared folder is never deleted by any single package uninstaller — it is preserved so other installed packages, continue to function.

    • CN-based stale CA deletion has been removed — the old behaviour of deleting any cert with CN T1C Local Root CA before install would wipe a valid CA owned by a co-installed package. Cleanup is now thumbprint-exact.

    Certificate management has been extracted into a CertmgrService struct with zero actix-web imports:

    • All business logic (cert generation, store install/uninstall, hosts management, status queries) lives in certmgr_service.rs and can be called from desktop apps, CLI tools, or test harnesses without spinning up an HTTP server.

    • The actix-web handler file (certmgr.rs) is a thin shim: parse request → call service → wrap HttpResponse.

    • Root CA installed into the macOS System Keychain via security add-trusted-cert -d -r trustRoot. A one-time marker file prevents re-prompting on every restart.

    • Elevation uses a native password dialog (sudo -A + SUDO_ASKPASS) — the same mechanism as mkcert.

    • Root CA installed into LocalMachine\Root (machine-wide, no per-user dialog). When the MSI runs as SYSTEM, the CA is written before the user ever opens a browser.

    • The API seeds the CA from the MSI install directory (C:\Program Files\<ConnectorName>\) so the trust store entry is correct even if the LocalAppData folder doesn't exist yet.


    The Distribution Service (DS) sync and the t1c-reg registry daemon cron are now fully non-blocking at startup:

    • DS client (mod_ds): initial sync and the recurring cron are spawned in a Tokio background task. The HTTP server starts immediately — a slow or unreachable DS no longer delays the API from accepting requests.

    • DS request timeouts: 15 s overall request timeout + 10 s connect timeout added to the reqwest fallback client. A misconfigured or offline DS endpoint can no longer cause an indefinite hang.

    • Configuration always present: the file exchange config file is now guaranteed to exist on the user profile, preventing crashes on first-time use.

    • Type deletion fixed: deleting a type that no longer exists no longer causes a panic — the operation returns a clean error.

    • Content sorting is now applied consistently across all list and type

    • Network-path quoting fix: VDDS executable command arguments containing UNC paths (\\server\share\...) or paths with spaces are now passed as raw strings, preventing shell-parsing issues on Windows.

    • Optional quote-stripping: a flag controls whether surrounding quotes are removed from path parameters, resolving edge cases when callers pre-quote their arguments.

    • Commands that reference network locations now work reliably without manual workarounds.

    All remaining panic! / unwrap() / .expect() call sites replaced with graceful error handling:

    Module
    Location
    Old behaviour
    New behaviour

    • CCID driver fix applied automatically on first startup (macOS Sonoma 14.x and later only; silently skipped on older releases).

    • Rosetta 2 is installed if not already present, ensuring Intel card reader drivers run correctly on Apple Silicon Macs.

    • Both actions are idempotent — they run once and are skipped on subsequent starts.

    • Root CA lookup now checks both LocalMachine\Root and CurrentUser\Root so the API correctly recognises a CA that was installed by an earlier version or by a user-level certutil call.

    • AKID/SKID certificate chain mismatch on Windows fixed by rebuilding the CA in memory from the DER-encoded bytes after disk load (avoids OpenSSL extension round-trip loss).


    The Microsoft Visual C++ Redistributable (vc_redist.x64.exe) is now embedded directly in every MSI. During installation:

    1. The registry key HKLM\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64\Installed is checked.

    2. If the runtime is already present, installation is skipped — no duplicate installs.

    3. If absent, it is installed silently (/quiet /norestart) before any connector files are placed.

    This eliminates the VCRUNTIME140.dll is missing error on bare Windows machines.

    Previous versions could leave locked file handles when upgrading or uninstalling while the API was running. The installer now:

    1. Force-terminates the full process tree (t1c-launch.exe, <app>-api.exe, <app>-sandbox.exe, t1c-reg.exe) with taskkill /F /T before any file operations.

    2. Waits 2 seconds for the OS to release all file handles.

    Runtime files (LocalAppData\<ConnectorName>\) — device keys, ds-txs.json, and logs — are removed on a full uninstall only. On an upgrade, the folder is intentionally preserved so device keys and sync state survive. The shared LocalAppData\T1CConnector\ cert folder is never deleted by any single package uninstaller — it is preserved for reuse across all T1C packages on the same device.

    A helper script is now included in C:\Program Files\<ConnectorName>\install-ca.bat. Administrators and Intune deployments can run this to (re-)install the Root CA without reinstalling the connector. The script:

    • Reads the CA file from the shared cert folder %LocalAppData%\T1CConnector\t1c-ca.pem (written by the API on first run).

    • Removes any stale T1C Local Root CA entry before adding the new one.

    • Returns an exit code that Intune Remediations can act on.

    package.bat now locates signtool.exe automatically by walking all installed Windows SDK versions under Program Files (x86)\Windows Kits\10\bin\. No more build failure when the SDK is installed but not on PATH.

    All five MSI packages now start the API with the -f (--enable-file-logger) flag, both at install time and in the login startup registry key. The log file is written to:

    This path can be targeted by Intune's Collect diagnostics feature or a PowerShell Remediation script.


    The previous collection of single-architecture shell scripts has been replaced with two comprehensive scripts:

    Script
    Platform
    Targets
    Notes

    Old scripts removed: build-arm.sh, build-intel.sh, build-windows.bat.

    A new docs/src/build-environment.md document covers the full build environment setup for both platforms, including the ClangCL VS component required for Windows ARM64.

    • AWS_LC_SYS_CMAKE_BUILDER=1 added to .cargo/config.toml — removes the libclang build-time dependency and makes the build fully reproducible on machines without LLVM installed.

    • Test certificate files and old t1c.zip artifacts removed from the repository to reduce attack surface and repository size.


    Scenario
    Behaviour

    Removal of Trust1Connector

    Page describing various ways to remove the Trust1Connector from your system

    Windows

    The installer for the Trust1Connector in windows leverages the MSI packaging system. This means that an application can be managed by the windows system.

    The uninstall process will remove the Trust1Connector in its entirity. But will run first a migration function that will store some data that can be used across multiple versions.

    Uninstalling such application can be done in multiple ways

    Command line

    First go to the location of where the MSI file is located and then execute (dont forget to change the filename to the name you have on your system.

    msiexec.exe /x "trust1connector_x64.msi"

    Settings window

    Via the windows settings menu you can find the installed applications and search for the Trust1Connector.

    Click on the 3 dots (windows 11) or on the application and choose uninstall.

    This will spawn the same flow as you would have when you double click the MSI file and clikc on the uninstall button.

    Via the MSI file you can double click the file and it will spawn a window asking to repair or remove. Here you can opt to remove the application

    The uninstall process will remove the Trust1Connector in its entirity. But will run first a migration function that will store some data that can be used across multiple versions.

    In MacOS you can remove the Trust1Connector in 2 ways;

    First of all open a terminal window

    When that has opened you need to change your current directory to the installed location of the Trust1Connector. This is located in your home library and using the command below you will go there;

    now you are in the folder and can run the uninstall script

    This will output something similar to this, after this you can close the terminal and the Trust1Connector is uninstalled.

    Like the Windows counter variant we have a way to uninstall without a command line. In MacOS this is via an application. The logo for that application looks like the image below.

    This application can be found in the .dmg file but also in the installed location which can be found in the following location (via terminal)

    the uninstall process is for Windows and MacOS the same, meaning it will first migrate the current configuration if there is one. and then continue with the uninstall process.

    At this point the migration process only stores the configuration of the File Exchange in the user path as a back-up when installing a new version of re-installing the same version.

    Diplad (BeLawyer)

    Each lawyer in Belgium registered at the balie is obliged since 1/1/2018 to have an electronic lawyer card. This is declared in atr. 193bis of the :

    “De advocaat moet voor zijn identificatie en voor de authenticatie beschikken over de elektronische CCBE-advocatenkaart.”

    More info at .

    All model information can be found in the

    Response will look like:

    Response will look like:

    Status codes / error handeling

    In the Trust1Connector V3 we've completely reworked the error system. The goal of this system is to have error codes which are easy to read, understand and integrate. Our first implementation was a very generic approach with as few error codes as possible.

    After some iterations of the Trust1Connector we've discovered that the old error system did not suffice the needs of integrators. So we've upgraded the system to be more consistent and extensive. This provides integrators the flexibility to have a very detailed error handeling system while keeping it easy to understand and read.

    The new system provides information about the origin, type and detailed information of the error. We maintained the same type (integers) as our previous error codes, this makes it easier to differentiate them.

    T1C uses response codes when handling a request.

    In case of an error the response will contain a body with more detailed information about the error:

    Jcop3*

    The following page describes how you can integrate the Jcop3 module exposed on the Trust1Connector onto your web application.

    All model information can be found in the

    Initialise a Trust1Connector client with a valid configuration:

    In order to get all connected card-readers, with available cards:

    This function call returns:

    Using the generic interface can be done as follows;

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the jcop3 integration.

    Eherkenning

    The following page describes how you can integrate the Eherkenning module exposed on the Trust1Connector onto your web application.

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    Chambersign*

    The Chambersign token is a token that requires for the middleware of Chambersign to be installed prior to using it on the Trust1Connector.

    All model information can be found in the

    Initialise a Trust1Connector client with a valid configuration:

    In order to get all connected card-readers, with available cards:

    This function call returns:

    Using the generic interface can be done as follows;

    Windows

    Initially when starting the application, and no Trust1Connector has been installed the following layout will be presented:

    The Home Page allows the user to download the Trust1Connector or view which version is currently installed. Although the connector can determine which operating system is running the browser, the page shows all possible downloads. Available installers are provided for:

    • Windows 32/64 bit (LTS)

    • Mac Intel/ARM (LTS)

    sha512
    sha3_256
  • sha3_384

  • sha3_512

  • sha256

    sha512

    sha512

    any other value

    sha256

    sha2_512

    sha3_256

    sha3_256

    sha3_384

    sha3_384

    sha3_512

    sha3_512

    sha256

    sha3_256

    sha384

    sha3_384

    sha512

    sha3_512

    any other value

    sha3_256

    sha512
    sha3_256
  • sha3_384

  • sha3_512

  • sha256

    sha512

    sha512

    any other value

    sha256

    sha2_512

    sha3_256

    sha3_256

    sha3_384

    sha3_384

    sha3_512

    sha3_512

    sha256

    sha3_256

    sha384

    sha3_384

    sha512

    sha3_512

    any other value

    sha3_256

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities. The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

    Generated Challenge

    A server generated challenge can be provided to the JavaScript library. In order to do so, an additional contract must be provided with the 'OCV API' (Open Certificate Validation API).

    Provided algorithm value

    Selected algorithm by T1C

    md5

    md5

    sha1

    sha1

    Provided algorithm value

    Selected algorithm by T1C

    sha2_256

    sha2_256

    sha2_384

    sha2_384

    SHA256

    SHA384

    SHA512

    Provided algorithm value

    Selected algorithm by T1C

    md5

    md5

    sha1

    sha1

    Provided algorithm value

    Selected algorithm by T1C

    sha2_256

    sha2_256

    sha2_384

    sha2_384

    Cardholder Information

    Biometric data

    Address

    Picture

    Token info

    Token version

    Certificates

    Extended certificates

    Root Certificate

    Authentication Certificate

    Intermediate Certificate (citizen)

    Non-repudiation Certificate

    Encryption Certificate (RRN)

    Data Filter

    Filter Card Holder Data

    Options are; biometric, picture and address

    Filter Certificates

    Sign Data

    Algorithm

    Belgian EID 1.7

    Belgian EID 1.8

    Signing

    Signing with a Crelan card reader

    Crelan card readers only support nl, fr, and de as languages

    Sign Hash without pin-pad

    Response of Sign returns a base64 encoded value which is the signature data. For belgian eid 1.8 this uses ECDSA and these signatures are returned in plain format, encoded as a direct concatenation of two byte strings r || s. This is also referred as PLAIN_ECDSA

    For more information on this you can visit the specification

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    SHA3 digest is used for the new Belgian eID cards (v1.8). The Trust1Connector falls back in this situation by using implicitly a SHA2 digest.

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Calculate Hash

    Example Hashes

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Verify PIN - retries left

    Authentication

    Algorithm

    Belgian EID 1.7

    Belgian EID 1.8

    Get valid algorithms to use for Sign or Authenticate

    Bulk Sign Reset
    calculate SHA256
    hex to base64 converter
    http://www.fileformat.info/tool/hexdump.htm
    Error codes page

    sha256

    sha2_512

    sha256

    sha2_512

    Localhost and local IP SAN entries (127.0.0.1, ::1, localhost) are included automatically.
  • Enabled by default. No configuration flag or extra step is needed.

  • Stale certificates are replaced on each startup — the API deletes old leaf cert files before writing new ones to ensure no stale material is used.

  • REST endpoints remain unchanged: GET /v3/certmgr/status[/{domain}], POST /v3/certmgr/install, POST /v3/certmgr/renew, POST /v3/certmgr/hosts, DELETE /v3/certmgr/uninstall.
    Firefox is trusted via the enterprise policy (policies.json + user.js) — no NSS certutil or Homebrew needed.
    ERR_CERT_AUTHORITY_INVALID in Chrome and Edge is resolved automatically on install.
    Registry daemon (t1c-reg): the cron that polls t1c-reg is spawned via tokio::spawn (replacing actix_rt::spawn) and carries a 5 s connect + 10 s request timeout. The HttpServer no longer blocks waiting for the daemon to respond before it begins serving.
    responses; helper functions have been extracted for reuse.
  • Origin and FileX config handling refactored to eliminate duplication across endpoints.

  • All remaining unwrap() calls replaced with proper error handling — the module can no longer cause an API process crash through file operations.

  • unwrap() panics

    Returns Err to caller

    system.rs

    start_sandbox_no_logging

    .expect() panic on spawn

    Logs error, returns 0

    system.rs

    start_registry

    .expect() panic on spawn

    Logs error, returns 0

    api.rs

    certmgr SSL init

    panic!

    error! log + process::exit(1)

    API-wide

    Option/Result chains

    unwrap()

    Explicit match / ? propagation

    Firefox: SEC_ERROR_REUSED_ISSUER_AND_SERIAL eliminated by randomising the leaf certificate serial on every generation.

  • Windows Storage dependency updated (windows crate) for compatibility with latest SDK.

  • Proceeds with file removal — no more "Access is denied" errors.

    x64, x86, ARM64

    ARM64 requires VS 2022 ARM64 CMake component + ClangCL; see docs/src/build-environment.md

    WiX extension NuGet packages pinned to exact version [4.0.5] across all five MSI projects — prevents a repeat of the Binary:Wix4UtilCA_x64 linker error caused by a silent NuGet auto-update.

    Full uninstall

    LocalAppData removed; Root CA removed from trust store; shared cert folder preserved

    Intune / MDM silent deploy

    No UAC dialogs; CA trusted under SYSTEM context; log available for Intune diagnostics

    macOS Apple Silicon

    Rosetta 2 installed on first run; CCID fix applied on Sonoma 14+

    Shared cert store

    All four cert files live in %LocalAppData%\T1CConnector\ — shared across all T1C packages on the same device

    CertmgrService

    Certificate management extracted into a reusable library layer with zero actix-web dependencies

    File Exchange

    Stability overhaul — guaranteed config, fixed type-deletion edge cases, improved sorting and listing

    FileEx module

    Command-path quoting fixes for Windows UNC/network paths; raw-string parameter handling

    macOS connectivity

    Automatic CCID driver fix (Sonoma 14+) and Rosetta 2 install on first startup

    Windows connectivity

    Root CA seeded from the MSI install directory; trust-store written to LocalMachine\Root without elevation dialogs

    Installers

    VC++ 2015–2022 runtime bundled; process-kill before uninstall; clean LocalAppData on uninstall; signtool auto-detection

    Logging

    File logging enabled by default; log stored at %LocalAppData%\<ConnectorName>\logs\t1c-api.log

    Startup stability

    DS sync and registry daemon crons are fully non-blocking; request timeouts prevent indefinite hangs

    Build scripts

    build-mac.sh (ARM + Intel) and build-windows.ps1 (x64 / x86 / ARM64) replace all previous build scripts

    mod_filex

    Multiple file operations

    unwrap() → process crash

    Returns Err, logged cleanly

    sec.rs

    build-mac.sh

    macOS (Apple Silicon host)

    ARM64 native + Intel (x86_64) cross

    Uses cross for Intel; produces universal-compatible artefacts

    build-windows.ps1

    Fresh install on a new machine

    VC++ runtime installed automatically; Root CA generated and trusted; logging active

    Upgrade from 3.8.9

    LocalAppData folder preserved (CA keys survive); running processes killed cleanly before file replacement

    Multiple T1C packages on same device

    Shared %LocalAppData%\T1CConnector\ cert folder reused — only one Root CA generated; all packages trust it

    New Features

    Localhost SSL — automatic certificate lifecycle

    Shared cert store — %LocalAppData%\T1CConnector\

    CertmgrService — reusable library layer

    macOS trust automation

    Windows trust automation

    Stability Improvements

    Startup — non-blocking DS sync and registry daemon

    File Exchange module (mod_filex)

    VDDS module (mod_vdds)

    API core — panic elimination

    Platform — macOS

    Platform — Windows

    Installer improvements

    VC++ 2015–2022 Runtime bundled

    Process-kill before uninstall / upgrade

    Clean LocalAppData on full uninstall

    Root CA fallback script (install-ca.bat)

    Signtool auto-detection

    File logging enabled by default

    Build & CI

    New release build scripts

    Other CI changes

    Upgrade notes

    rotate_device_cert

    Windows

    Response will look like:

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Response will look like:

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Response will look like:

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Response will look like:

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Response will look like:

    • If the card reader has a PIN pad, the PIN must always be entered via the card-reader PIN pad.

    • If the card reader has no PIN pad:

      • If the osDialog property is set to true, a OS dialog window will be displayed for the user the enter their PIN

      • If the pin property is defined, that value is used

      • If osDialog is set to false, and pin is undefined, an error will be returned

    Response will look like:

    To sign data, an algorithm must be specified in the algorithm property (see Supported Algorithms), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.

    Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk PIN Reset method is called.

    The PIN can provided/entered in the same way as Verify PIN

    Response will look like:

    To sign data, an algorithm must be specified in the algorithm property (see Supported Algorithms), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.

    The PIN can provided/entered in the same way as Verify PIN

    Response will look like:

    Response will look like:

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Interface

    Module

    Models

    Examples

    Initializing Diplad Module

    All Data

    Biometric Data

    Picture

    Codex Deontologie voor Advocaten
    https://www.diplad.be/en-GB/t/23/elektronische-advocatenkaart.aspx
    Token typings model page

    All Certificates

    The filter is optional

    Root Certificate

    Authentication Certificate

    Non-Repudiation Certificate

    Verify PIN

    Sign

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Authenticate

    Get Supported Algorithms

    Bulk PIN Reset

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'root certificate' or 'Issuer certificate stored on the smart card. The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Middleware of Eherkenning has to be installed to be able to fully use the Eherkenning token.

    Supported version of the middleware is; Windows: 3.5.3.0 - 64bit & 32bit MacOS: 3.5.3.0

    Interface

    Token info

    Certificates

    Extended certificates

    Authentication Certificate

    Non-repudiation Certificate

    Encryption Certificate

    Root Certificate/Issuer Certificate

    Filter Certificates

    Sign Data

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly.

    Sign data without pin-pad

    Sign Hash with pin-pad

    Validate signature

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the chambersign integration.

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks

    Chambersign introduction

    The middleware of Chambersign has to be installed to be able to fully use the Chambersign

    The version of the middleware supported is; Mac: 6.17.1 Windows: 6.12.0

    Interface

    Models

    Initialise the Trust1Connector JS

    Obtain the Reader information

    Token typings model page

    Token info

    Certificates

    Authentication Certificate

    Non-repudiation Certificate

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": ["Belgian eID Card"]
          },
          "id": "57a3e2e71c48cee9",
          "name": "Bit4id miniLector",
          "pinpad": false
        }
      ],
      "success": true
    }
    var beid = client.beid(reader_id);
    client.beid(reader_id).biometric(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "birthDate": "15 JUL  1993",
     "birthLocation": "Roeselare",
     "cardDeliveryMunicipality": "Avelgem",
     "cardNumber": "592..8233",
     "cardValidityDateBegin": "27.05.2015",
     "cardValidityDateEnd": "27.05.2025",
     "chipNumber": "U0xHk...EstwAjEpJQQg==",
     "documentType": "01",
     "firstNames": "Gilles Frans",
     "name": "Platteeuw",
     "nationalNumber": "930...154",
     "nationality": "Belg",
     "nobleCondition": "",
     "pictureHash": "Fqva9YCp...JKyn8=",
     "rawData": "AQw1OTIxMjQwNTgy...TARFBar2vWAqTW+axEIuyskBgFySsp/",
     "sex": "M",
     "signature": "hKys9WMjUm4ipg...14xUCg/98Y9/gP/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
     "specialStatus": "0",
     "thirdName": "J",
     "version": "0"
    }
    client.beid(reader_id).address(callback);
    {
     "municipality": "Hoeselt",
     "rawData": "ARJLZXJrc...AAAAAA==",
     "signature": "mhPyeRg25H...w==",
     "streetAndNumber": "Kerkstraat X",
     "version": "0",
     "zipcode": "3730"
    }
    client.beid(reader_id).picture(callback);
    {
      "data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
      "success": true
    }
    {
        "info": {
            "rawData": "string",
            "version": "string",
            "serialNumber": "string",
            "label": "string",
            "prnGeneration": "string",
            "eidCompliant": "string",
            "graphicalPersoVersion": "string",
            "versionRfu": "string",
            "electricalPersoVersion": "string",
            "electricalPersoInterfaceVersion": "string",
            "changeCounter": "number",
            "activated": "string",
        },
        "infoType": "Token"
    }
    client.beid(reader_id).tokenVersion(callback);
    
    {
     "success": true,
     "data": {
      "version": "1.7"
     }
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    intermediateCertificatesExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "intermediateCertificates": {
                "certificates": [...]
            },
            "encryptionCertificate": {
                "certificates": [...]
            }
       }
    }
    client.beid(reader_id).rootCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).authenticationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).intermediateCertificates(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).nonRepudiationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).encryptionCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    client.beid(reader_id).allData({ filters: filter}, callback);
    {
     "picture": {
      "picture": "/9j/4AAQSkZJRgABAgEBLAEsAAD/...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"
     },
     "biometric": {
      "birthDate": "15 JUL  1993",
      "birthLocation": "Roeselare",
      "cardDeliveryMunicipality": "Avelgem",
      "cardNumber": "592124058233",
      "cardValidityDateBegin": "27.05.2015",
      "cardValidityDateEnd": "27.05.2025",
      "chipNumber": "...==",
      "documentType": "01",
      "firstNames": "Gilles Frans",
      "name": "Platteeuw",
      "nationalNumber": "...",
      "nationality": "Belg",
      "nobleCondition": "",
      "pictureHash": "...=",
      "rawData": "...+axEIuyskBgFySsp/",
      "sex": "M",
      "signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
      "specialStatus": "0",
      "thirdName": "J",
      "version": "0"
     },
     "address": {
      "municipality": "Hoeselt",
      "rawData": "...==",
      "signature": "...+Evety1PnTE4pqXaHgBxIpk+P8kRL5W3zDV+../../..+YoHBC9KqTmSpl5KULxdnKiyCt+2RyJdzE2wyoymjRmysIhJy1wW9PRnx99S1TFqQLuc0tyBmkBPR4aFqmOq4a7zqd0q2Q1g+BbnwJ4d3oa10ia5+0kBXf0THoXv3HYIHlnwhBMfAtWzPnFrYBuAKTwyl7yBF5IFfXFpGWuVZUTJElgNcmNvsHMnAhVwDw==",
      "streetAndNumber": "Kerkstraat X",
      "version": "0",
      "zipcode": "3730"
     }
    }
    var filter = ['biometric'];
    client.beid().allData({ filters: filter }, callback);
    {
     "biometric": {
      "birthDate": "15 JUL  1993",
      "birthLocation": "Roeselare",
      "cardDeliveryMunicipality": "Avelgem",
      "cardNumber": "592124058233",
      "cardValidityDateBegin": "27.05.2015",
      "cardValidityDateEnd": "27.05.2025",
      "chipNumber": "...==",
      "documentType": "01",
      "firstNames": "Gilles Frans",
      "name": "Platteeuw",
      "nationalNumber": "...",
      "nationality": "Belg",
      "nobleCondition": "",
      "pictureHash": "...=",
      "rawData": "...+axEIuyskBgFySsp/",
      "sex": "M",
      "signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
      "specialStatus": "0",
      "thirdName": "J",
      "version": "0"
     }
    }
    var filter = [];
    client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var filter = ['rootCertificate'];
    client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     }
    }
    var filter = null;
    client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true,
          "txId": "1234",
          "language": "fr"
    }
    client.beid(reader_id).sign(data, callback);
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true
    }
    client.beid(reader_id).sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false
    }
    client.beid(reader_id).sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    beid.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = true;
    beid.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    beid.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    This is sample text to demonstrate siging with Belgian eID
    135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b
    E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
    }
    client.beid(reader_id).signData(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=
    7B8F4654076B80EB963911F19CFAD1AAF4285ED48E826F6CDE1B01A79AA73FADB5446E667FC4F90417782C91270540F3
    TbwLx5Vw+RK6ETqvkzJ8JKIkLRX8zR8+KGU7I9of90YxOXkn3GjftmWEBXpFgBit+VWGBmr+Do886sqM0R5L9w==
    var data = {
          "pin":"..."
    }
    client.beid(reader_id).verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {}
    client.beid(reader_id).verifyPin(data, callback);
    {
      "verified": true
    }
      $("#buttonValidate").on('click', function () {
          var _body={};
          _body.pin = $("#psw").val(); //only when no pin-pad available
          var beid = client.beid(reader_id);
          beid.verifyPin(_body, validationCallback);
      });
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.beid(reader_id).authenticate(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    The calculated digest of the hash is prefixed with:
    DigestInfo ::= SEQUENCE {
          digestAlgorithm AlgorithmIdentifier,
          digest OCTET STRING
      }
    Make sure this has been taken into consideration in order to validate the signature in a backend process.
    generic.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    %LocalAppData%\T1CConnector\
        t1c-ca.pem          ← Root CA certificate (PEM)
        t1c-ca-key.pem      ← Root CA private key
        t1c-tls.pem         ← localhost TLS leaf certificate
        t1c-tls-key.pem     ← localhost TLS private key
    %LocalAppData%\<ConnectorName>\logs\t1c-api.log
    export interface AbstractEidDiplad {
       allData(filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
      allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      biometric(callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
      tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
      address(callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
      picture(callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
      rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      intermediateCertificates(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      intermediateCertificatesExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    T1cSdk.initialize(config).then(res => {
        const diplad = res.client.createEidDiplad(readerId);
    }, err => {
        console.error(error)
    });
    diplad.allData().then(res => {
    }, err => {
       console.log(err);
    }
    {
      "data": {
        "biometric": {
          "cardNumber": "cardNumber",
          "cardValidityDateEnd": "2021-01-08",
          "chipNumber": "c57c0a3f-d034-46c9-831e-a208b2e44fb6",
          "firstNames": "Tom",
          "name": "Van Cammen",
          "nationality": "BE",
          "rawData": "BASE64_ENCODED_CARD_DATA",
          "version": "1",
          "issuer": ""
        },
        "picture": {
          "picture": "BASE64_ENCODED_BYTE_ARRAY"
        }
      },
      "success": true
    }
    diplad.biometric().then(res => {
    }, err => {
       console.log(err);
    }
    {
      "data": {
        "cardNumber": "cardNumber",
        "cardValidityDateEnd": "2021-01-08",
        "chipNumber": "c57c0a3f-d034-46c9-831e-a208b2e44fb6",
        "firstNames": "Tom",
        "name": "Van Cammen",
        "nationality": "BE",
        "rawData": "BASE64_ENCODED_CARD_DATA",
        "version": "1",
        "issuer": ""
      },
      "success": true
    }
    diplad.picture().then(res => {
    }, err => {
       console.log(err);
    }
    {
      "data": {
        "picture": "BASE64_ENCODED_BYTE_ARRAY"
      },
      "success": true
    }
    const filter = ['rootCertificate', 'authenticationCertificate', 'nonRepudiationCertificate'];
    diplad.allCerts(parseCertsBoolean, filter).then(res => {
    }, err => {
       console.log(err);
    }
    {
        success: true,
        data: {
           authenticationCertificate?: {
                 certificate?: string,
                 certificates?: Array<string>,
                 certificateType?: string,
                 id?: string,
                 parsedCertificate?: Certificate,
                 parsedCertificates?: Array<Certificate>
           },
           
           nonRepudiationCertificate?: {
                 certificate?: string,
                 certificates?: Array<string>,
                 certificateType?: string,
                 id?: string,
                 parsedCertificate?: Certificate,
                 parsedCertificates?: Array<Certificate>
           },
           rootCertificate?: {
                 certificate?: string,
                 certificates?: Array<string>,
                 certificateType?: string,
                 id?: string,
                 parsedCertificate?: Certificate,
                 parsedCertificates?: Array<Certificate>
           },
        }
    }
    diplad.rootCertificate(parseCertsBoolean).then(res => {
    }, err => {
       console.log(err);
    }
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    diplad.authenticationCertificate(parseCertsBoolean).then(res => {
    }, err => {
       console.log(err);
    }
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    diplad.nonRepudiationCertificate(parseCertsBoolean).then(res => {
    }, err => {
       console.log(err);
    }
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    const data = {
        pin: "1234", // optional
        osDialog: true // optional
    }
    diplad.verifyPin(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": {
          "verified": true
        }    
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = false;
    diplad.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": {
          "data": "..."
        }    
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    diplad.authenticate(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": {
          "data": "..."
        }    
    }
    diplad.allAlgoRefs().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": {
          "ref": ["sha1", "sha256", "sha512"]
        }    
    }
    diplad.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    export interface AbstractEherkenning {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "encryptionCertificate": {
                "certificates": [...]
            },
            "rootCertificate": {
                "certificates": [...]
            }        
       }
    }
    generic.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    generic.rootCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    generic.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var filter = ['authenticationCertificate'];
    generic.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     }
    }
    var filter = null;
    module.allCerts({ filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    module.signRaw(data, callback);
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": true
    }
    module.sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm": "sha256",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": false
    }
    module.sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    safenet.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    export interface AbstractChambersign {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
    }
    
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }
    const moduleName = "chambersign";
    var module = client.generic(selected_reader.id);
    var module = client.chambersign(selected_reader.id);
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    module.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    module.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var filter = ['authenticationCertificate'];
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     }
    }
    var filter = null;
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    chambersign.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = true;
    module.sign(module, data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    module.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {}
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    module.authenticate(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    module.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    module.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    Error codes will be in the following number format
    XXXXXX
    for example
    201010
    is an error code that depicts an error occurred with the reader in the Transaction service.

    The first digit depicts the Origin of that error, values can be the following;

    Error

    Origin

    1XXXXX

    General

    2XXXXX

    Transaction service

    The following 2 digits describe the type of error;

    Error

    Type

    X01XXX

    Reader

    X02XXX

    Card

    Finally we have 3 digits that give a more detailed error. These will give you more information about the specific error-case. Currently we have the following exceptions that can be thrown.

    Code

    Exception type

    10000

    GeneralConnectorException

    XXX000

    InvalidDigestException

    The following list are codes that you can expect.

    Error code

    Description

    111003

    Module not implemented

    106029

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error code

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error

    Description

    312998

    Module not implemented

    611004

    Parameter error

    Error

    Description

    505126

    Configuration error / none is found

    504123

    Access exception/ not enough access rights - General error

    Old code

    New code

    example description

    351

    504128

    /Library/Updates/ProductMetadata2.plist (Operation not permitted)

    352

    The most simple way you can check the error codes is by only taking into account the latest 3 digits. The first 3 digits provide information about the Context and environment

    {
      description: "some error description",
      code: "some error code"
    }
    

    Introduction

    Status Codes

    Error format

    Codes to expect

    General / Controller

    Aventry My Id 4

    Oberthur 7.3

    Idemia cosmo 8.2

    BeID

    Diplad

    Luxtrust

    Luxeid

    EMV

    Crelan

    File exchange

    Error codes coming from v2

    Simple error handeling

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    Data can be signed using the Jcop3 smart card. To do so, the T1C-GCL facilitates in:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    export interface AbstractJcop {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }
    const moduleName = "jcop3";
    var module = client.generic(selected_reader.id);

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Interface

    Models

    Initialise the Trust1Connector JS

    Obtain the Reader information

    Token typings model page
    var module = client.jcop3(selected_reader.id);
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            }
            "encryptionCertificate": {
                "certificates": [...]
            }
       }
    }
    module.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.encryptionCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    module.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
     ...
     },
     "encryptionCertificate": {
     ...
     }
    }
    var filter = ['authenticationCertificate'];
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     }
    }
    var filter = null;
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true,
          "id": "id.."
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false,
          "id": "id.."
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    module.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234",
        id: "id.."
    }
    const bulk = true;
    module.sign(module, data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    module.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {}
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "id": "id.."
    }
    module.authenticate(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    module.verifyPin(module, data, callback);
    module.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    module.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }

    Token info

    Certificates

    Extended certificates

    Authentication Certificate

    Non-repudiation Certificate

    Encryption Certificate

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Check the before signing with a defined algorithm

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify pin only check the global sign pin at this moment

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

  • Linux (Ubuntu/Debian or other upon request)

  • After the downloaded, the signed package can be installed on your system. The connector has been build to have a small footprint. After a successful installation, the page must be refreshed. The application has been build to avoid explicit polling of readers prior to the installation.

    The installation wizard will be started when the downloaded installer is executed:

    Installation Wizard Starts

    Installation Wizard Finished

    The Trust1Connector SDK determines the targeted operating system and provides the user with a appropriate download link.

    Installation

    cd ~/Library/Application\ Support/Trust1Team/Trust1Connector/
    ./uninstall.sh
    Uninstalling Trust1Connector
    version: 3.6.0
     module: trust1team_launch
      May 24 13:16:04.627 INFO Operating system: macos
      May 24 13:16:04.627 INFO Installation folder: "/Users/gilles/Library/Application Support/Trust1Team/Trust1Connector"
      May 24 13:16:04.627 INFO Starting migration
     module: trust1team_launch::commons
      May 24 13:16:04.627 INFO Migrate Trust1Connector Common
      May 24 13:16:04.627 INFO Stop service Common
      May 24 13:16:04.627 INFO Stop service Common
      May 24 13:16:04.631 INFO No file exchange configuration found; No such file or directory (os error 2)
     module: trust1team_launch
      May 24 13:16:04.631 INFO Launcher ended successfully
    The application is not part of the firewall 
    The application is not part of the firewall 
    The application is not part of the firewall 
    Uninstall Trust1Connector Completed with status OK
    cd ~/Library/Application\ Support/Trust1Team/Trust1Connector/
    open .

    MSI file

    MacOS

    Terminal

    Uninstall application

    Uninstall process

    Idemia Cosmo One v8.2

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The ID-One Cosmo V8-n is part of the Idemia IAS ECC family of cryptographic modules called ID-One Cosmo V8. Modules within this family share the same functionalities and the description of the ID-One Cosmo V8 applies to all versions including the “-n” subject to this validation. This document describes the functionality provided by the Idemia IAS ECC ID-One smartcard - which is a PKI container - on the T1C-GCL (Generic Connector Library) implemented version:

    • ID-One Cosmo V8-n; FIPS 140-2 Security Policy

    Interface

    export interface AbstractIdemia {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
        rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    

    Models

    All model information can be found in the Token typings model page

    Examples

    Create the Idemia module

    T1cSdk.initialize(config).then(res => {
        const idemia = res.client.idemia(readerId);
    }, err => {
        console.error(error)
    });

    When initialisation is finished you can continue using the aventra object to execute the functions below.

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    The expected response for this call should be;

    The expected response for this call should be;

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    The expected response for this call should be;

    This will return information of the Aventra card.

    The expected response for this call should be;

    When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.

    Contains the 'root certificate' stored on the smart card. The service can be called:

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:

    The expected response for these calls should be in the following format;

    The expected response for these calls should be in the following format;

    Data can be signed using the smartcard. To do so, the SDK facilitates in:

    • Retrieving the certificate chain (root, intermediate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To sign data, an algorithm must be specified in the algorithm property (see ), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.

    Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The expected response for this call should be;

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    The SDK is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process

    The expected response for this call should be;

    The expected response for this call should be;

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Airbus

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The following page describes how you can integrate the Airbus module exposed on the Trust1Connector onto your web application.

    Interface

    export interface AbstractEidGeneric {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Initialise the Trust1Connector JS

    Initialise a Trust1Connector client with a valid configuration:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Obtain the Reader information

    In order to get all connected card-readers, with available cards:

    var core = client.core();
    core.readersCardAvailable(callback);

    This function call returns:

    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }

    Using the generic interface can be done as follows;

    const moduleName = "airbus";
    var module = client.generic(selected_reader.id);

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the jcop3 integration.

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'root certificate' or 'Issuer certificate stored on the smart card. The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    Data can be signed using the Jcop3 smart card. To do so, the T1C-GCL facilitates in:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Certigna*

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks

    Introduction

    The following page describes how you can integrate the Certigna module exposed on the Trust1Connector onto your web application.

    The middleware of Certigna has to be installed to be able to fully use the Certigna token.

    The version of the middleware supported is; Mac: Mac M1: Windows:

    Interface

    export interface AbstractCertigna {
        allCertFilters(): string[];
        allKeyRefs(): string[];
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Initialise the Trust1Connector JS

    Initialise a Trust1Connector client with a valid configuration:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Obtain the Reader information

    In order to get all connected card-readers, with available cards:

    var core = client.core();
    core.readersCardAvailable(callback);

    This function call returns:

    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }

    Using the generic interface can be done as follows;

    const moduleName = 'certigna';
    var module = client.generic(selected_reader.id);

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the certigna integration.

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Luxembourg ID

    The Luxembourg ID container facilitates communication with card readers with inserted Luxembourg ID smart card. The JS client library provides function to communicate with the smart card and facilitates integration into a web or native application. This document describes the functionality provided by the Luxembourg ID module

    The Abstract Lux eID interface is summarized in the following snippet:

    Each interface will be covered on this wiki, accompanied with example code and response objects.

    For more information on how to configure the T1C-JS client library see . Initialize a gclClient:

    Get the Luxembourg ID container service:

    Note that we pass both the reader_id,

    Safenet*

    The following page describes how you can integrate the Safenet module exposed on the Trust1Connector onto your web application.

    All model information can be found in the

    Initialise a Trust1Connector client:

    Get the container service:

    Call a function for the Belgian eID container:

    The constructor for the Belgian eID expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:

    3XXXXX

    Certificate service

    4XXXXX

    Meta service

    5XXXXX

    File exchange

    6XXXXX

    Identity service

    7XXXXX

    Reader service

    8XXXXX

    Proxy

    9XXXXX

    System

    X03XXX

    Notification

    X04XXX

    Security

    X05XXX

    Configuration

    X06XXX

    Input

    X07XXX

    Session

    X08XXX

    PIN

    X09XXX

    PUK

    X10XXX

    Pace

    X11XXX

    Module

    X12XXX

    System

    X13XXX

    I/O

    X14XXX

    Consent

    X15XXX

    Agent

    XXX001

    ModuleNotSupportedException

    XXX002

    ModuleNotAvailableException

    XXX003

    ModuleNotImplementedException

    XXX004

    FunctionNotSupportedException

    XXX005

    FunctionNotAvailableException

    XXX006

    FunctionNotImplementedException

    XXX007

    ServiceNotSupportedException

    XXX008

    ServiceNotAvailableException

    XXX009

    ServiceNotImplementedException

    XXX010

    ReaderException

    XXX011

    ReaderTimeoutException

    XXX012

    ReaderProviderException

    XXX013

    ReaderNotAvailableException

    XXX014

    ReaderCancelledException

    XXX020

    InitialisationException

    XXX021

    DistributionServiceException

    XXX022

    GenericRestException

    XXX023

    JsonParseException

    XXX024

    JWTParseException

    XXX025

    ForbiddenException

    XXX026

    UnauthorisedException

    XXX028

    DeviceKeyStoreMissingException

    XXX029

    ParamRestException

    XXX030

    ProxyServiceException

    XXX031

    InvalidStateException

    XXX032

    DeviceKeyException

    XXX040

    TransactionException

    XXX041

    TransactionNotFoundException

    XXX042

    TransactionNotSupportedException

    XXX043

    TransactionProviderException

    XXX044

    ApplicationLockedException

    XXX045

    PaceLayerException

    XXX046

    TransactionPinBlockedException

    XXX047

    TransactionInvalidPinException

    XXX048

    TransactionPukBlockedException

    XXX049

    TransactionInvalidPukException

    XXX050

    TransactionPinTimeoutException

    XXX051

    TransactionPinCancelledException

    XXX052

    TransactionSignAuthenticateErrorException

    XXX053

    CardProtocolException

    XXX054

    ApduException

    XXX060 - XXX069

    TransactionPukException

    XXX070 - XXX079

    TransactionPinException

    XXX090

    EncryptionException

    XXX100

    CertificateException

    XXX101

    CertificatePinException

    XXX102

    CertificateNotFoundException

    XXX103

    CertificateProviderException

    XXX104

    MetaException

    XXX105

    MetaPinException

    XXX106

    MetaNotFoundException

    XXX107

    MetaProviderException

    XXX110

    PKCS11Exception

    XXX111

    PKCS11ProviderException

    XXX120

    FileExchangeException

    XXX121

    IoException

    XXX123

    AccessException

    XXX124

    TypeException

    XXX125

    EntityException

    XXX126

    ConfigurationException

    XXX127

    ContentException

    XXX128

    AccessReadException

    XXX129

    AccessWriteException

    XXX130

    AccessExecuteException

    XXX131

    FileNotFoundException

    XXX132

    FileAlreadyExistsException

    XXX133

    TypeAlreadyExistsException

    XXX135

    MatrixPrinterException

    XXX140

    NotificationException

    XXX998

    InternalErrorException

    XXX999

    ConnectorNotAvailableException

    XXX501

    ConsentException

    XXX500

    AgentNotFoundException

    XXX200

    InvalidSessionException

    XXX201

    InvalidAtrException

    XXX300

    SecurityException

    XXX996

    ClientErrorException (invalid input body or request was send)

    XXX997

    SandboxRuntimeException (failure in the sanbox, API will implicitly restart the sandbox)

    105126

    Configuration error

    112031

    Invalid T1C state error

    104025

    Forbidden exception

    814501

    Consent error

    815500

    Agent not found

    104000

    Invalid digest error

    104021

    Error contacting or retrieving info from Distribution service

    104020

    Error initialising T1C

    104030

    Error contacting or getting info from the proxy

    104028

    Device keystore missing

    104027

    DS JWE error

    104026

    Unauthorised

    104027

    Forbidden

    104024

    JWT parsing error

    104023

    JSON parsing error

    100890

    Decryption exception, pin or puk or pace value could not be decrypted

    106997

    Invalid input body or request has been send to the API

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    209048

    Puk blocked

    209049

    invalid puk

    209062

    Invalid puk 2 retries remain

    209061

    invalid puk 1 retry remain

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208074

    invalid Pin 4 retries remain

    208073

    invalid Pin 3 retries remain

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208074

    invalid Pin 4 retries remain

    208073

    invalid Pin 3 retries remain

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    209048

    Puk blocked

    209049

    invalid puk

    209064

    Invalid puk 4 retries remain

    209063

    Invalid puk 3 retries remain

    209062

    Invalid puk 2 retries remain

    209061

    invalid puk 1 retry remain

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    411004

    Invalid T1C state error

    212998

    Forbidden exception

    211004

    Function not supported

    202040

    Card error

    302040

    Card error

    402040

    Card error

    602040

    Card error

    206029

    Parameter exception

    208072

    invalid Pin 2 retries remain

    208071

    invalid Pin 1 retry remain

    206046

    Pin blocked

    206047

    invalid pin

    201051

    Pin cancelled

    2015050

    Pin timeout

    202010

    Card not present

    302010

    Card not present

    602010

    Card not present

    513121

    I/O error

    504128

    Read rights missing

    504129

    Write rights missing

    504130

    Execute rights missing

    513124

    Type error

    513125

    Entity error

    513127

    Content error / file not found

    503140

    Notification error, when a OS dialog returns an error

    513131

    File not found

    513132

    File already exists

    504129

    /Library/Updates/ProductMetadata2.plist (Operation not permitted)

    353

    504130

    /Library/Updates/ProductMetadata2.plist (Operation not permitted)

    354

    513121

    Source '/Users/gilles/Desktop/fileextest/test.plist' does not exist

    355

    503140

    No valid dir path returned, no valid file path returned, Timeout, No PIN entered

    356

    513124

    No Type with name test was found in entity with name testEnt,

    357

    513124

    type with name testType already exists

    358

    513131 or 513132

    FIle not found or File already exists

    359

    not applicable

    360

    513125

    Entity with name testEnt already exists

    361

    513125

    No Entity with name testEnt was found

    /

    505126

    No configuration found (file-exchange config file is missing/deleted…)

    valid algorithm options

    Token info

    All certificate filters

    Extended certificates

    all Key references

    all Certificates

    Token data

    Certificate

    Root certificate

    Authentication certificate

    Non repudiation certificate

    Issuer certificate

    Encryption certificate

    Verify pin

    Sign

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk PIN Reset

    Authenticate

    Retrieve supported algorithms

    Validate signature

    Supported Algorithms
    Bulk PIN Reset

    Token info

    Certificates

    Extended certificates

    Authentication Certificate

    Non-repudiation Certificate

    Encryption Certificate

    Root Certificate/Issuer Certificate

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    Bulk Sign Reset

    Token info

    Certificates

    Extended certificates

    Authentication Certificate

    Non-repudiation Certificate

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    Bulk Sign Reset
    6.11.9.1 (supports up until MacOS 10.15 at the time of integration)
    6.17.1.0
    6.12.0.0

    Payment typing models

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    This page describes all generic payment models used.

    Models

    This function call returns:

    All methods for safenet will use the selected reader - identified by the reader_id.

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'citizen CA certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not. The service can be called:

    Response:

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the citizen certificate stored on the smart card. The 'citizen certificate' is used to sign the 'authentication certificate' and the 'non-repudiation certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    Data can be signed using the Belgian eID smart card. To do so, the T1C-GCL facilitates in:

    • Retrieving the certificate chain (citizen-certificate, root-certificate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

      Response:

      Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities. The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

      Generated Challenge

      A server generated challenge can be provided to the JavaScript library. In order to do so, an additional contract must be provided with the 'OCV API' (Open Certificate Validation API).

    Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    Introduction

    Middleware of Safenet has to be installed to be able to fully use the Safenet token.

    Supported version of the middleware is; Windows: 10.2 - 64bit & 32bit MacOS: 10.2

    Interface

    Models

    Get Safenet container object

    Obtain the Reader-ID

    Token typings model page

    Token info

    Certificates

    Extended certificates

    Root Certificate

    Authentication Certificate

    Intermediate Certificate (citizen)

    Non-repudiation Certificate

    Encryption Certificate

    Data Filter

    Filter Certificates

    Sign Data

    Signing

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly.

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerCertificateExtended(parseCerts?: boolean,  callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "rootCertificate": {
                "certificates": [...]
            },
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "encryptionCertificates": {
                "certificates": [...]
            },
            "issuerCertificates": {
                "certificates": [...]
            }
       }
    }
    idemia.allCertFilters().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate', 'nonRepudiationCertificate', 'issuerCertificate']
    }
    idemia.allKeyRefs().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: ['authenticate', 'sign', 'encrypt']
    }
    const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
    idemia.allCerts(filter).then(res => {
        res.data
    }, err => {
        console.error(err)
    })
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    idemia.tokenData().then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
           version?: string,
           serialNumber?: string,
           label?: string,
           changeCounter?: number,
        }
    }
    idemia.rootCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    idemia.authenticationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    idemia.nonRepudiationCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    idemia.issuerCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    aventra.encryptionCertificate(parseCertsBoolean).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    const data = {
        pin: "1234", // optional
        osDialog: true // optional
    }
    idemia.verifyPin(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            "verfied": true
        }
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        id: "123"
    }
    const bulk = false;
    idemia.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false,
          "id" : "fewf5+65"
    }
    idemia.signRaw(data, callback);
    idemia.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        id: "123"
    }
    idemia.authenticate(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            data: string
        }
    }
    idemia.allAlgoRefs(data).then(res => {
    }, err => {
        console.error(err)
    })
    {
        success: true,
        data: {
            ref: ['sha256', 'md5']
        }
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    safenet.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    var module = client.airbus(selected_reader.id);
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "encryptionCertificate": {
                "certificates": [...]
            },
            "rootCertificate": {
                "certificates": [...]
            }        
       }
    }
    module.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.rootCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    module.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var filter = ['authenticationCertificate'];
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     }
    }
    var filter = null;
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true,
          "id": "id.."
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false,
          "id": "id.."
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    module.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234",
        id: "id.."
    }
    const bulk = true;
    module.sign(module, data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    module.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {}
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "id": "id.."
    }
    module.authenticate(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    module.verifyPin(module, data, callback);
    module.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    module.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    var module = client.certigna(selected_reader.id);
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            }
       }
    }
    module.authenticationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    module.allCerts(parseCerts, { filters: filter}, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = ['authenticationCertificate'];
    module.allCerts({ filters: filter}, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = null;
    module.allCerts({ filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": true
    }
    module.sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm": "sha256",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": false
    }
    module.sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    module.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = true;
    module.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    client.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    module.verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {}
    module.verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha256",
      "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
    }
    module.authenticate(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    module.allAlgoRefs(callback);
    {
        "success": true,
        "data": ["sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    module.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    export class PaymentModuleDescriptionResponse extends DataObjectResponse {
      constructor(public data: PaymentModuleDescription, public success: boolean) {
        super(data, success);
      }
    }
    
    export class PaymentModuleDescription {
      constructor(
          public desc: string
      ) {}
    }
    
    
    export class PaymentVerifyPinResponse extends DataObjectResponse {
      constructor(public data: PaymentVerifyPinResponseData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class PaymentVerifyPinResponseData {
      constructor(
          public verified: boolean
      ) {}
    }
    
    export class PaymentReadData {
      constructor(
          public applications: Array<PaymentApplication>,
      ) {}
    }
    
    export class PaymentApplication {
      constructor(
          public aid?: string,
          public name?: string,
          public priority?: number,
      ) {}
    }
    
    
    export class PaymentReadDataResponse extends DataObjectResponse {
      constructor(public data: PaymentReadData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class PaymentReadApplicationData {
      constructor(
          public country?: string,
          public countryCode?: string,
          public effectiveDate?: string,
          public expirationDate?: string,
          public language?: string,
          public name?: string,
          public pan?: string,
      ) {}
    }
    
    export class PaymentReadApplicationDataResponse extends DataObjectResponse {
      constructor(public data: PaymentReadApplicationData, public success: boolean) {
        super(data, success);
      }
    }
    
    export class PaymentSignResponseData {
      constructor(public success: boolean, public data?: string, public cardSignature?: string, public readerSignature?: string) {
      }
    }
    
    export class PaymentSignResponse {
      constructor(public data: PaymentSignResponseData, public success: boolean) {}
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.safenet(reader_id).authenticate(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    export interface AbstractSafenet {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
    }
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var client = client.safenet(reader_id);
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    beid.biometric(callback);
    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        {
          "card": {
            "atr": "3B9813400AA503010101AD1311",
            "description": [""]
          },
          "id": "57a3e2e71c48cee9",
          "name": "JC Token",
          "pinpad": false
        }
      ],
      "success": true
    }
    client.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
       }
    }
    client.beid(reader_id).rootCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).authenticationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).intermediateCertificates(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).nonRepudiationCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.beid(reader_id).encryptionCertificate(parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var filter = ['rootCertificate'];
    client.safenet(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     }
    }
    var filter = null;
    client.safenet(reader_id).allCerts(parseCerts, { filters: filter}, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true
    }
    client.safenet(reader_id).sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false
    }
    client.safenet(reader_id).sign(data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    client.signRaw(data, callback);
    var data = {
          "pin":"..."
    }
    client.safenet(reader_id).verifyPin(data, callback);
    {
      "verified": true
    }
    var data = {}
    client.safenet(reader_id).verifyPin(data, callback);
    {
      "verified": true
    }
    The calculated digest of the hash is prefixed with:
    DigestInfo ::= SEQUENCE {
          digestAlgorithm AlgorithmIdentifier,
          digest OCTET STRING
      }
    Make sure this has been taken into consideration in order to validate the signature in a backend process.
    client.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    client.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    pin
    and
    pinType
    code in this call. Unlike other cards, all communication with the Luxembourg ID card is protected with the PIN/CAN code.

    Call a function for the Luxembourg ID container:

    For demonstration purpose we will use the aforementioned callback, which only outputs the data and eventual error messages. During integration meaningful functionality should be provided.

    The pin should be provided in order to instantiate the container. It's is possible to enforce user PIN entry for each function separately. Providing the PIN at instantiation of the container, means that the PIN will be in the browser session - but not persisted - for the lifetime of the container instance within the browser session.

    The constructor for the Luxembourg ID expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see . Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:

    This function call returns:

    We notice that a card object is available in the response in the context of a detected reader. The reader in the example above is iDentiv CL, has no pin-pad capabilities, and there is a card detected with given ATR and description "Grand Duchy of Luxembourg...". An ATR (Answer To Reset) identifies the type of a smart-card. The reader, has a unique ID, reader_id; this reader_id must be used in order to request functionalities for the Luxembourg eID card. This must be done upon instantiation of the container:

    All methods for luxeid will use the selected reader - identified by the reader_id.

    The card holder is the person identified using the Luxembourg eID card. It's important to note that all data must be validated in your backend. Data validation can be done using the appropriate certificate (public key).

    Contains all biometric related data, excluding the card holder address and picture. The service can be called:

    An example callback:

    Response:

    Contains the card holder's address. The service can be called:

    Response:

    Contains the card holder's picture stored on the smart card. The service can be called:

    Response:

    Contains an image of the card holder's signature stored on the smart card. The service can be called:

    Response:

    Exposes all the certificates publicly available on the smart card. The following certificates can be found on the card:

    • Root certificate

    • Intermediate certificate

    • Authentication certificate

    • Non-repudiation certificate

    T1C-JS will return the raw base64 certificate, optionally it can also return an object representing the certificate as parsed by PKI.js. To enable parsing, parseCerts must be set to true.

    The root and intermediate certificates are both stored as root certificates.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'intermediate certificate'. The service can be called:

    Response:

    There are 2 root certificates on the card, one is the issuer certificate of the intermediate

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:

    Response:

    All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the 'rn', 'picture' and 'rrn certificate':

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the 'root-certificate' and the 'rrn-certificate':

    Response:

    Data can be signed using the Luxembourg ID smart card. To do so, the T1C-GCL facilitates in:

    • Retrieving the certificate chain (root, inetermediate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The 'authentication_reference' property can contain the following values: sha1, sha256, sha512, md5.

    Avoid using SHA-1: is deprecated on the interface and will not be available in the future

    In order to calculate a hash from the data to sign, you need to know the algorithm you will use in order to sign. You might have noticed the algorithm_reference property provided in the sign request. The algorithm_reference can be one of the values: md5, sha1, sha256, sha512. For example, we want the following text to be signed using sha256:

    You can use the following online tool to calculate the SHA256: calculate SHA256

    Hexadecimal result:

    Notice that the length of the SHA256 is always the same. Now we need to convert the hexadecimal string to a base64-encoded string, another online tool can be used for this example: hex to base64 converter

    Base64-encoded result:

    Now we can sign the data:

    Result:

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    In order to inform a user upon the PIN retries left, the Luxembourg eID doesn't provide a request to retrieve this information. After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

    Note that, when the user has at least one retry left,entering a correct PIN resets the PIN retry status.

    For more information about the error codes you can check the Error codes page

    The T1C is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

      var data = {
        "pin": "...",
        "algorithm": "sha1",
        "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
      }
      client.luxeid(reader_id, pin).authenticate(data, callback);

      Response:

      {
      "success": true,
      "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
      }

      Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities. The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

      Generated Challenge

      A server generated challenge can be provided to the JavaScript library. In order to do so, an additional contract must be provided with the 'OCV API' (Open Certificate Validation API).

    The functions specified are asynchronous and always need a callback function. The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:

    The error object returned:

    For the error codes and description, see .

    export interface AbstractEidLux {
    allData(filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
      allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      biometric(callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
      tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
      address(callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
      picture(callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
      rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;}
    
    
    export class PinType {
      static PIN = 'Pin';
      static CAN = 'Can';
    }
    
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });
    var module = client.luxeid(reader_id, pin, pinType);

    Introduction

    Interface Summary

    Get Luxembourg ID container object

    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    module.biometric(callback);
    var core = client.core();
    core.readersCardAvailable(callback);
    {
      "data": [
        {
          "card": {
            "atr": "3B8F800180318065B0850300EF120FFF82900073",
            "description":["Grand Duchy of Luxembourg / Identity card with LuxTrust certificate (eID)"
          },
          "id": "57a3e2e71c48cee9",
          "name": "iDentiv CL",
          "pinpad": false
        }
      ],
      "success": true
    }
    var module = client.luxeid(reader_id, pin, pinType);
    client.luxeid(reader_id, pin, pinType).biometric(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      "data": {
        "birthDate": "830819",
        "documentNumber": "SPEC04168",
        "documentType": "ID",
        "firstName": "SPECIMEN",
        "gender": "F",
        "issuingState": "LUX",
        "lastName": "SPECIMEN",
        "nationality": "LUX",
        "validityEndDate": "251116",
        "validityStartDate": "151116"
      },
      "success": true
    }
    client.luxeid(reader_id, pin, pinType).address(callback);
    {
      "data": {
        //TBD
      },
      "success": true
    }
    client.luxeid(reader_id, pin, pinType).picture(callback);
    {
      "data": {
        "height": 320,
        "image": "/0//UQAvAAAAAADwAAABQAAAAAAAAAAAAAAA8AAA....uq9eK159DRO61Ufrf9ICA/9k=",
        "width": 240
      },
      "success": true
    }
    client.luxeid(reader_id, pin, pinType).signatureImage(callback);
    {
      "data": {
        "image": "/0//UQAvAAAAAADwAAABQAAAAAAAAAAAAAAA8AAA....uq9eK159DRO61Ufrf9ICA/9k=",
        "raw_data": "/0//UQAAAAAADwAAARLKEQDAAAAAAAAAAAAAA8AAA....dl42fgr367PCSA321/9k="
      },
      "success": true
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    encryptionCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "rootCertificate": {
                "certificates": [...]
            }        
       }
    }
    client.luxeid(reader_id, pin, pinType).rootCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.luxeid(reader_id, pin, pinType).authenticationCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.luxeid(reader_id, pin, pinType).nonRepudiationCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    client.luxeid(reader_id, pin, pinType).allData({ filters: filter, parseCerts: true }, callback);
    {
      "data": {
        "authentication_certificate": {
          "base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
          "parsed": { // parsed certificate object }
        },
        "biometric": {
          "birthDate": "830819",
          "documentNumber": "SPEC04168",
          "documentType": "ID",
          "firstName": "SPECIMEN",
          "gender": "F",
          "issuingState": "LUX",
          "lastName": "SPECIMEN",
          "nationality": "LUX",
          "validityEndDate": "251116",
          "validityStartDate": "151116"
        },
        "non_repudiation_certificate": {
          "base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
          "parsed": { // parsed certificate object }
        },
        "picture": {
          "height": 320,
          "image": "/0//UQAvAAAAAADwAAABQAAAAAAAAAA...f9ICA/9k=",
          "width": 240
        },
        "root_certificates": [
          {
            "base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
            "parsed": { // parsed certificate object }
          },
          {
            "base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
            "parsed": { // parsed certificate object }
          }
        ]
      },
      "success": true
    }
    // filter entries := ["authentication-certificate","biometric","non-repudiation-certificate","picture","root-certificates"]
    var filter = ["biometric","authentication-certificate"];
    client.luxeid(reader_id, pin, pinType).allData({ filters: filter, parseCerts: true }, callback);
    {
      "data": {
        "biometric": {
          "birthDate": "830819",
          "documentNumber": "SPEC04168",
          "documentType": "ID",
            "firstName": "SPECIMEN",
            "gender": "F",
            "issuingState": "LUX",
            "lastName": "SPECIMEN",
            "nationality": "LUX",
            "validityEndDate": "251116",
            "validityStartDate": "151116"
        },
        "authentication_certificate": {
          "base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
          "parsed": { // parsed certificate object }
        }
      },
      "success": true
    }
    var filter = [];
    client.luxeid(reader_id, pin, pinType).allCerts({ filters: filter, parseCerts: true }, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     },
     "intermediateCertificates": {
      ...
     },
     "encryptionCertificate": {
      ...
     }
    }
    // filter entries := ["authentication-certificate","non-repudiation-certificate","root-certificates"];
    var filter = ['authentication-certificate'];
    client.luxeid(reader_id, pin, pinType).allCerts({ filters: filter, parseCerts: true }, callback);
    {
     "authenticationCertificate": {
      ...
     },
    }
    var filter = ['root-certificates','authentication-certificate','non-repudiaton-certificate'];
    client.luxeid(reader_id, pin, pinType).allCertificates({ filters: filter, parseCerts: false }, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.luxeid(reader_id, pin, pinType).sign(data, callback);
    {
      "success": true,
      "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
    }
    This is sample text to demonstrate siging with Luxembourg eID
    135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b
    E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
    }
    client.luxeid(reader_id, pin, pinType).sign(data, callback);
    {
      "data": "C7SG5eix1+lzMcZXgL0bCL+rLxKhd8ngrSj6mvlgooWH7CloEU13Rj8QiQHdhHnZgAi4Q0fCMIqAc4dn9uW9OP+MRitimRpYZcaDsGrUehPi/JpOD1e+ko7xKZ67ijUU4KTmG4HXc114oJ7xxx3CGL7TNFfvuEphLbbZa+9IZSSnYDOOENJqhggqqu7paSbLJrxC2zaeMxODKb5WSexHnZH6NnLPl2OmvPTYtxiTUMrLbFRsDRAziF6/VQkgM8/xOm+1/9Expv5DSLRY8RQ+wha6/nMlJjx50JszYIj2aBQKp4AOxPVdPewVGEWF4NF9ffrPLrOA2v2d7t5M4q7yxA==",
      "success": true
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    luxidClient.signRaw(data, callback);
    var data = {
          "pin":"..."
    }
    client.luxeid(reader_id, pin, pinType).verifyPin(data, callback);
    {
      "success": true
    }
      $("#buttonValidate").on('click', function () {
          var _body={};
          _body.pin = $("#psw").val(); //only when no pin-pad available
          var luxeid = client.luxeid(reader_id, pin, pinType));
          luxeid.verifyPin(_body, validationCallback);
      });
    The calculated digest of the hash is prefixed with:
    DigestInfo ::= SEQUENCE {
          digestAlgorithm AlgorithmIdentifier,
          digest OCTET STRING
      }
    Make sure this has been taken into consideration in order to validate the signature in a backend process.
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      success: false,
      description: "some error description",
      code: "some error code"
    }

    Obtain the Reader-ID

    Cardholder Information

    Biometric Information

    Address

    Picture

    Signature Image

    Certificates

    Certificate Chain

    Extended certificates

    Root Certificate

    Authentication Certificate

    Non-repudiation Certificate

    Data Filter

    Filter Card Holder Information

    Filter Certificates

    Sign Data

    Sign Hash

    Calculate Hash

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly.

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN - retries left

    Authentication

    Error Handling

    Error Object

    Client Configuration

    Truststore API

    This module is available starting from v3.8.5

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The Truststore API has been introduced to allow using any PKCS11 compatible smart card, which is available in the OS certificate or keystore. The Trust1Connector will interface to the Windows Certificate manager or the Mac Keystore using native OS mappings.

    Certificates available in the certificate manager or keystore will be availabe through the generic Trust1Connector interface.

    Interface

    export interface AbstractTruststore {
      allCerts(filters?: string[] | Options): Promise<GenericT1CResponse<TruststoreAllCertificatesResponse>>;
      rootCertificates(): Promise<GenericT1CResponse<CertificatesResponse>>;
      intermediateCertificates(): Promise<GenericT1CResponse<CertificatesResponse>>;
      authenticationCertificates(): Promise<GenericT1CResponse<CertificatesResponse>>;
      nonRepudiationCertificates(): Promise<GenericT1CResponse<CertificatesResponse>>;
      encryptionCertificates(): Promise<GenericT1CResponse<CertificatesResponse>>;
      getCertificate(id: string): Promise<GenericT1CResponse<TruststoreCertificate>>;
    
      verifyPin(body: TruststoreVerifyPinRequest): Promise<GenericT1CResponse<boolean>>;
      authenticate(body: TruststoreAuthenticateOrSignRequest): Promise<GenericT1CResponse<TruststoreAuthenticateOrSignResponse>>;
      sign(body: TruststoreAuthenticateOrSignRequest, bulk?: boolean): Promise<GenericT1CResponse<TruststoreAuthenticateOrSignResponse>>;
      allAlgoRefs(): Promise<GenericT1CResponse<string>>;
      resetBulkPin(): Promise<GenericT1CResponse<boolean>>;
    }

    Models

    All model information can be found in the Token typings model page

    Get Truststore container object

    Initialise a Trust1Connector client:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Get the container service:

    var ts = client.truststore();

    Call a function for the container:

    ts.allCerts();

    Certificates

    Exposes all the certificates publicly available on the store.

    this has the capabilities to return multiple certificates if the store has multiple of any type.

    Below you can find all the functions to retrieve a specific type of certificates

    Response:

    You can also fetch all the certificates, separated by type, at once

    To get the certificates necessary for signature validation in your back-end:

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    To get the certificates necessary for signature validation in your back-end:

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    Introduction

    The Truststore is an add-on to the Trust1Connector that enables you to use PKCS#11 smart cards for authentication and signing. The Truststore is available as of version 3.8. By default it is NOT enabled.

    Important difference between Modules and the Truststore

    There is an important difference between a smart card that is read via the Truststore or directly via the Trust1Connector. Smart Cards that are implemented in the Trust1Connector are called Modules. A Module will return ALL information and certificates available on the Smart Card to the consuming application. The Truststore only reads the certificates of the Smart Card and can therefor only be used in authentication and signing use cases.

    High Level Technical Introduction

    The Truststore is an add-on to the Trust1Connector that enables you to use PKCS#11 smart cards for authentication and signing. The Truststore is available as of version 3.8. By default it is NOT enabled.

    Important difference between a module and the Truststore

    There is an important difference between smart cards that are read via the Truststore or directly via the Trust1Connector. Cards that are implemented in the Trust1Connector are called modules. A modules will return ALL the available information and certificates of the smart card to the consuming application. The Truststore only reads the certificates of the smart cards and can therefor only be used for authentication and signing use cases.

    The Truststore is an add-on to the Trust1Connector that enables you to use PKCS#11 smart cards for authentication and sign The Truststore is available as of version 3.8. By default it is NOT enabled.

    Important difference between a Module and the Truststore

    The Truststore module for the Trust1Connector interfaces with the respective Certificate Manager and KeyChain of Windows and Mac OS.

    The store (used further as a shorthand for Truststore) implements the following use cases:

    • detecting the certificates in the personal certificate store which can be used for authentication and signing

    • X509 parsing of the certificates, and exposing the certificates through the T1C

    • resolving the supported signature algorithms which can be used for the selected certificate

    1. The vendor specific driver is considered installed on OS level.

    This means that the smart card will be detected by the Operating System in the context of the certificate manager of keychain.

    When the requirement to access smart cards WITHOUT installation of the vendor specific driver is applied, the specific smart card MUST be implemented in a separate Module, or the driver library MUST be localized throughout the PKCS11 module of the T1C.

    In the former case, the smart card communication and model is implemented in a separate T1C Module.

    In the latter, we require the driver is located somewhere on the OS (from T1C v3.5) or can be shipped/provisioned through the Distribution Server (from DSv4).

    1. The smart card driver supports the PKCS#11 standard for Public Key Cryptography API

    Vendors provide smart cards and smart card readers. Each smart card must have a Cryptographic Service Provider (CSP) that uses the CryptoAPI interfaces to enable cryptographic operations and the WinSCard APIs to enable communications with smart card hardware.. For the Truststore this MUST be the PKCS#11 API.

    The following diagram shows the Cryptography architecture that is used by the Windows operating system. The implementation uses CNG (Crypto Next Generation - NCrypt.dll) to interact natively with the underlying system.

    The implementation uses CNG (Crypto Next Generation - NCrypt.dll) to interact natively with the underlying system

    According to Mac the Keychain is the best place to store small secrets like cryptographic keys. So that is why we are using it. The implementation uses CryptoTokenKit to interact natively with the underlying system.

    Card behaviour in Mac OSX is different from Windows. When a user physically inserts a smart card or token into a USB slot or card reader—the CryptoTokenKit framework exposes the token’s items to your app as standard keychain items. It does this by copying the items to the keychain when the token is inserted, and deleting them from the keychain when the token is removed.

    This is quite simple. After installing the driver for the card, insert the card in a card reader connected to or a USB-slot of your computer.

    When the framework copies an item from a token to the keychain, it records the associated token’s identifier, or token ID, as part of the keychain item. If you know the token ID, you can use it to very precisely filter the keychain search. Do this by including the key in the query dictionary. For example, to get a reference to a key that comes from a token with token ID com.example.piv:0123456789, use the search query:

    To identify token IDs that are currently available in the system, use an instance of the class. This object has a property that’s a list of all the token IDs present in the system. You can read this at any time:

    LuxTrust

    Introduction

    The LuxTrust smartcard container facilitates communication with card readers with inserted LuxTrust smartcards and LuxTrust Signing Sticks. The T1C-JS client library provides function to communicate with the smart card and facilitates integration into a web or native application. This document describes the functionality provided by the LuxTrust smartcard - which is a PKI container

    Interface Summary

    The Abstract LuxTrust smartcard interface is summarized in the following snippet:

    export interface AbstractLuxTrust {
      allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
      rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
      nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
      allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
      rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
      nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
      verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
      authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
      sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
      allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
      resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }

    Additional Remarks

    The LuxTrust Signing Stick can be seen as an smartcard integrated in an USB smartcard reader. The use cases described in this wiki are valid for both LuxTrust smartcards as LuxTrust Signing Stick, as there a no technical implementation differences.

    Retrieve a connected card reader

    In order to start with any use case, we need to select a card reader. The targeted reader will be passed as a parameter to the subsequent methods provided. This is part of the core Trust1Connector functionality. More information about core service functionality can be found on the following page: .

    For demonstration purpose we'll add a simple console output callback, which we'll use throughout the documentation.

    Just as an example, we instantiate a new gcl (local client) and ask for all connected smart card readers:

    This will returns us all connected readers:

    In the example you'll notice that we are using a dual interface uTrust reader and a card has been inserted.

    The reader id 'c8d31f8fed44d952' can be used as parameter in the next steps in order to select a smartcard reader for the functionality we want to execute. The pinpad property can be used to decided whether to pass the pin property to the reader (e.g. when verifying the pin).

    Exposes all the certificates publicly available on the smart card. The following certificates can be found on the card:

    • Root certificate

    • Intermediate certificate

    • Authentication certificate

    T1C-JS will return the raw base64 certificate, optionally it can also return an object representing the certificate as parsed by . To enable parsing, parseCerts must be set to true.

    The root and intermediate certificates are both stored as root certificates.

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'intermediate certificate'. The service can be called:

    Response:

    There are 2 root certificates on the card, one is the issuer certificate of the intermediate

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the 'root-certificate' and the 'authentication_certificate':

    Response:

    Data can be signed using the LuxTrust smartcard and Signing Stick. To do so, the T1C-GCL facilitates in:

    • Retrieving the certificate chain (root, intermediate and non-repudiation certificate)

    • Perform a sign operation (private key stays on the smart card)

    • Return the signed hash

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The 'authentication_reference' property can contain the following values: sha1 and sha256.

    Avoid using SHA-1: is deprecated on the interface and will not be available in the future

    The LuxTrust smartcard and Signing Stick is not supporting SHA512 at the moment.

    In order to calculate a hash from the data to sign, you need to know the algorithm you will use in order to sign. You might have noticed the algorithm_reference property provided in the sign request. The algorithm_reference can be one of the values: sha1, sha256. For example, we want the following text to be signed using sha256:

    You can use the following online tool to calculate the SHA256:

    Hexadecimal result:

    Notice that the length of the SHA256 is always the same. Now we need to convert the hexadecimal string to a base64-encoded string, another online tool can be used for this example:

    Base64-encoded result:

    Now we can sign the data (remove the pin property for pinpad readers):

    Result:

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

    An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities. The 'algorithm_reference' property can contain the following values: sha1 and sha256.

    A server generated challenge can be provided to the JavaScript library. In order to do so, an additional contract must be provided with the 'OCV API' (Open Certificate Validation API).

    The functions specified are asynchronous and always need a callback function. The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:

    The error object returned:

    For the error codes and description, see ..

    Camerfirma*

    (prerequisite: Camerfirma driver needed)

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks

    Camerfirma introduction

    The Camerfirma token is a token that requires for the middleware of Camerfirma to be installed prior to using it on the Trust1Connector

    Interface

    export interface AbstractCamerfirma {
        allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
        authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
        nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
    
        allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        validateSignature(body: TokenValidateSignatureRequest, callback?: (error: T1CLibException, data: TokenValidateSignatureResponse) => void): Promise<TokenValidateSignatureResponse>;
    
        verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
        authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
        sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        signRaw(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
        allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        tokenData(callback?: (error: T1CLibException, data: TokenInfoResponse) => void): Promise<TokenInfoResponse>;
    }

    Models

    All model information can be found in the Token typings model page

    Initialise the Trust1Connector JS

    Initialise a Trust1Connector client with a valid configuration:

    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
    }, err => {
        console.error(error)
    });

    Obtain the Reader information

    In order to get all connected card-readers, with available cards:

    var core = client.core();
    core.readersCardAvailable(callback);

    This function call returns:

    {
      "data": [
        // List of reader with cards found
      ],
      "success": true
    }

    Using the generic interface can be done as follows;

    Because we're using the generic interface we can define the module variable upfront since we know we want to use the camerfirma integration.

    If you want to use the module directly you can initialise as folows (same functions are available but dont need the module to be included in the called function)

    You can fetch the token information via the function. this will give all the information of the token you need according to the PKCS11 specifications

    Exposes all the certificates publicly available on the smart card.

    Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:

    Response:

    All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:

    Response:

    The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate

    Response:

    To get the certificates necessary for signature validation in your back-end:

    Response:

    Depending on the connected smart card reader. A sign can be executed in 2 modes:

    • Using a connected card reader with 'pin-pad' capabilities (keypad and display available)

    • Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)

    Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.

    When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    When the pin entry is done on the pin-pad, the following request is used to sign a given hash:

    Response is a base64 encoded signed hash:

    The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.

    With the function signRaw you can sign unhashed document data. This means that the Trust1Connector will hash the value itself depending on the provided sign algorithm.

    Below you can find an example

    The function looks the same as a regular sign operation but expects a base64 data object that is unhashed.

    Supported hash functions (SHA2) are;

    • SHA256

    • SHA384

    • SHA512

    It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.

    The PIN set for bulk signing can be reset by calling this method.

    Response will look like:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:

    • provided by an external service

    • provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.

      External Challenge

      An external challenge is provided in the data property of the following example:

    Response:

    Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.

    Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate

    The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)

    The module allows you to call a function on the token that can validate a signature. For this we need to use the validateSignature function. You can call this one via;

    The response of this function will return a valid property that is either true or false.

    EMV*

    This container supports functionality for EMV "chip and PIN" bank cards, including:

    • VISA, MasterCard, Amex, CB and UK Post Office Account contact cards

    • PayWave (VISA) and PayPass (MasterCard) contactless cards

    Initialise a Trust1Connector:

    Crelan

    (prerequisite: driver installation neeeded)

    This container supports functionality for Crelan bank cards

    Initialise a Trust1Connector client:

    Get the Crelan module:

    Call a function for the Crelan module:

    The constructor for the Crelan expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see . Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:

    This function call returns:

    Fetching Certificate information

    Sign Data

    On MacOS it is not possible to provide a pin yet, this will be resolved in a future version; this feature depends on the availability of this funcitonality on the MacOS.

    Truststore pop-up for mac will open a session on the Keychain

    Sign Hash

    Authenticate Data

    On MacOS it is not possible to provide a pin yet, this will be resolved in a future version; this feature depends on the availability of this funcitonality on the MacOS.

    Truststore pop-up for mac will open a session on the Keychain

    Authenticate Hash

    Bulk Signing

    Bulk signing is not active yet for Truststore, this will be released in a later update.

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    On MacOS it is not possible to provide a pin yet, this will be resolved in a future version; this feature depends on the availability of this funcitonality on the MacOS.

    Verify PIN without pin-pad

    Bulk Sign Reset
    validates the hash received from the consuming application
  • signs a digest received from the consuming application

  • authenticates the user through a PIN verification flow

  • authenticates the user by signing a digest using the authentication certificate

  • High level technical solution

    Prerequisites

    Windows Certificate Manager

    Card behaviour in Windows

    Mac OSX Keychain

    Card behaviour in Mac OSX

    How to verify if a Smart Card is available for your OS?

    MAC OS

    Windows

    kSecAttrTokenID
    TKTokenWatcher
    tokenIDs
    scource: Smart Card Architecture
    source: using cryptographic assets

    Token info

    Certificates

    Authentication Certificate

    Non-repudiation Certificate

    Filter Certificates

    Sign Data

    Sign Hash without pin-pad

    Sign Hash with pin-pad

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly

    Bulk Signing

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Bulk PIN Reset

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Authentication

    Get valid algorithms to use for Sign or Authenticate

    Validate signature

    Bulk Sign Reset
    ts.authenticationCertificates().then().catch();
    ts.rootCertificates().then().catch();
    ts.intermediateCertificates().then().catch();
    ts.encryptionCertificates().then().catch();
    ts.nonRepudiationCertificates().then().catch();
    {
        success: true,
        data: {
            certificates: [{
                "certificate": "MIIEd..jRTii/DF8nHZiNmm5w==",
                "id": "4d4eebf..43ddf00042e",
                "subject": "C=B...ication)",
                "serialNumber": "10:00:00:00...2:e8:26:6e"
            }],     
        }    
    }
    let filter = new Options(['authenticationCertificate']) //filter out only AuthenticationCertificates
    // The filter parameter is optional
    ts.allCerts(filter).then().catch()
    {
      "success": true,
      "data": {
        "authenticationCertificate": {
          "certificates": [
            {
              "certificate": "MIAKBggqhkjOPQQDAwNnADBkAj5w==",
              "id": "4d4eebf5f4df00042e",
              "subject": "C=BEtication)",
              "serialNumber": "10:00:e8:26:6e"
            }
          ]
        }
      }
    }
    var filter = null;
    ts.allCerts({ filters: filter});
    var data = {
          "pin":"...",
          "certId:"...",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": true
    }
    ts.sign(data);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var filter = null;
    ts.allCerts({ filters: filter});
    var data = {
          "pin":"...",
          "certId:"...",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": true
    }
    ts.authenticate(data);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    const data = {
          "pin":"...",
          "certId:"...",
          "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
          "osDialog": true
    }
    const bulk = true;
    ts.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    ts.resetBulkPin().then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          pin?: string;
          osDialog?: boolean;
          timeout?: Number;
          certId?: string;
    }
    ts.verifyPin(data);
    {
        "success": true,
        "data": true
    }
    let getquery: [String: Any] = [kSecClass as String: kSecClassKey,
                                   kSecAttrTokenID as String: "com.example.piv:0123456789",
                                   kSecReturnRef as String: true]
    let watcher = TKTokenWatcher()
    print("The following token IDs are present in the system:")
    for tokenID in watcher.tokenIDs {
        print(tokenID)
    }
    const moduleName = "camerfirma";
    var module = client.generic(selected_reader.id);
    var module = client.camerfirma(selected_reader.id);
    module.tokenData().then(res => {
        // see response below
    })
    {
        "success": true,
        "data": {
            "info": {
                "slot": "string",
                "label": "string",
                "manufacturerId": "string",
                "model": "string",
                "serialNumber": "string",
                "flags": {
                    "isRandomNumberGenerator": "boolean",
                    "isWriteProtected": "boolean",
                    "isLoginRequired": "boolean",
                    "isUserPinInitialized": "boolean",
                    "isRestoreKeyNotNeeded": "boolean",
                    "isClockOnToken": "boolean",
                    "isProtectedAuthenticationPath": "boolean",
                    "isDualCryptoOperations": "boolean",
                    "isTokenInitialized": "boolean",
                    "isSecondaryAuthentication": "boolean",
                    "isUserPinCountLow": "boolean",
                    "isUserPinFinalTry": "boolean",
                    "isUserPinLocked": "boolean",
                    "isUserPinToBeChanged": "boolean",
                    "isSoPinCountLow": "boolean",
                    "isSoPinFinalTry": "boolean",
                    "isSoPinLocked": "boolean",
                    "isSoPinToBeChanged": "boolean"
                },
                "mechanisms": [
                    {
                        "mechanism": "string",
                        "flags": {
                            "isHardware": "boolean",
                            "isEncrypt": "boolean",
                            "isDecrypt": "boolean",
                            "isDigest": "boolean",
                            "isSign": "boolean",
                            "isSignRecover": "boolean",
                            "isVerify": "boolean",
                            "isVerifyRecover": "boolean",
                            "isGenerate": "boolean",
                            "isGenerateKeyPair": "boolean",
                            "isWrap": "boolean",
                            "isUnwrap": "boolean",
                            "isExtension": "boolean",
                            "isEcFP": "boolean",
                            "isEcNamedcurve": "boolean",
                            "isEcUncompress": "boolean",
                            "isEcCompress": "boolean"
                        },
                        "ulMinKeySize": "number",
                        "ulMaxKeySize": "number"
                    }
                ],
                "ulMaxSessionCount": "number",
                "ulSessionCount": "number",
                "ulMaxRwSessionCount": "number",
                "ulMaxPinLen": "number",
                "ulMinPinLen": "number",
                "ulTotalPubLicMemory": "number",
                "ulFreePubMemory": "number",
                "ulTotalPrivateMemory": "number",
                "ulFreePrivateMemory": "number",
                "hardwareVersion": "string",
                "firmwareVersion": "string"
            },
            "infoType": "TokenInfoType"
        }
    }
    
    
    
    //ENUM
    TokenInfoType {
        Token,
        PKCS11,
        File,
        Payment,
        HSM,
        Vault,
        Wallet,
    }
    module.authenticationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    module.nonRepudiationCertificate(module, parseCertsBoolean, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    module.allCerts(module, parseCerts, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var filter = ['authenticationCertificate'];
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     }
    }
    var filter = null;
    module.allCerts(module, { filters: filter}, callback);
    {
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": true
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
          "osDialog": false
    }
    module.sign(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    module.signRaw(data, callback);
    const data = {
        algorithm: "sha256",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        pin: "1234"
    }
    const bulk = true;
    module.sign(module, data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    module.resetBulkPin(module).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": true
    }
    var data = {
          "pin":"..."
    }
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {}
    module.verifyPin(module, data, callback);
    {
      "verified": true
    }
    var data = {
      "pin": "...",
      "algorithm": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    module.authenticate(module, data, callback);
    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }
    module.allAlgoRefs(module, callback);
    {
        "success": true,
        "data": ["sha1", "sha256"]
    }
    const body = {
        "algorithm": 'sha256',
        "hash": '...',
        "signedHash": '...',
        "osDialog": false,
        "id": 'cert_id',
        "pin": 'pin_code',
        "timeout": 120 //timeout in seconds
    }
    module.validateSignature(body).then(response => {
        response.valid
    ).catch(error => {
        errorHandler(error)}
    )
    {
        "success": true,
        "data": {
            "valid": true
        }
    }
    Non-repudiation certificate
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    T1CSdk.T1CClient.initialize(config).then(res => {
        client = res;
        client.core().readers(callback);
    }, err => {
        console.error(error)
    });
    {
      "data": [
        {
          "card": {
            "atr": "3B7D94000080318065B0831100C883009000",
            "description": [
              "personal identity card (ID card)",
              "LuxTrust card"
            ]
          },
          "id": "c8d31f8fed44d952",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(1)",
          "pinpad": false
        },
        {
          "id": "ec3109c84ee9eeb5",
          "name": "Identiv uTrust 4701 F Dual Interface Reader(2)",
          "pinpad": false
        }
      ],
      "success": true
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    authenticationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    nonRepudiationCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    rootCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,
                "certificateType"?: string,
                "id"?: string,
                "subject"?: string,
                "issuer"?: string,
                "serialNumber"?: string,
                "url"?: string,
                "hashSubPubKey"?: string,
                "hashIssPubKey"?: string,
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "authenticationCertificate": {
                "certificates": [...]
            },
            "nonRepudiationCertificate": {
                "certificates": [...]
            },
            "rootCertificate": {
                "certificates": [...]
            }        
       }
    }
    client.luxtrust(reader_id).rootCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.luxtrust(reader_id).authenticationCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    client.luxtrust(reader_id).signingCertificate({ parseCerts: true }, callback);
    {
        success: true,
        data: {
            certificate?: string,
            certificates?: Array<string>,
            certificateType?: string,
            id?: string,
            parsedCertificate?: Certificate,
            parsedCertificates?: Array<Certificate>
        }    
    }
    var filter = [];
    client.luxtrust(reader_id).allCerts({ filters: filter, parseCerts: true }, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var filter = ['authentication-certificate'];
    client.luxtrust(reader_id).allCerts({ filters: filter, parseCerts: true }, callback);
    {
     "rootCertificate": {
      ...
     }
    }
    var filter = ['root-certificates','authentication-certificate','signing-certificate'];
    client.luxtrust(reader_id).allCertificates({ filters: filter, parseCerts: false }, callback);
    {
     "rootCertificate": {
      ...
     },
     "authenticationCertificate": {
      ...
     },
     "nonRepudiationCertificate": {
      ...
     }
    }
    var data = {
          "pin":"...",
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.luxtrust(reader_id).sign(data, callback);
    var data = {
          "algorithm":"sha1",
          "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.luxtrust(reader_id).sign(data, callback);
    {
      "success": true,
      "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
    }
    This is sample text to demonstrate siging with LuxTrust smartcard or signing stick
    135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b
    E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=
    var data = {
          "pin":"...",
          "algorithm":"sha256",
          "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
    }
    client.luxtrust(reader_id).sign(data, callback);
    {
      "data": "C7SG5eix1+lzMcZXgL0bCL+rLxKhd8ngrSj6mvlgooWH7CloEU13Rj8QiQHdhHnZgAi4Q0fCMIqAc4dn9uW9OP+MRitimRpYZcaDsGrUehPi/JpOD1e+ko7xKZ67ijUU4KTmG4HXc114oJ7xxx3CGL7TNFfvuEphLbbZa+9IZSSnYDOOENJqhggqqu7paSbLJrxC2zaeMxODKb5WSexHnZH6NnLPl2OmvPTYtxiTUMrLbFRsDRAziF6/VQkgM8/xOm+1/9Expv5DSLRY8RQ+wha6/nMlJjx50JszYIj2aBQKp4AOxPVdPewVGEWF4NF9ffrPLrOA2v2d7t5M4q7yxA==",
      "success": true
    }
    var data = {
          "algorithm":"sha256",
          "data":"vl5He0ulthjX+VWNM46QX7vJ8VvXMq2k/Tq8Xq1bwEw=",
          "osDialog": false
    }
    luxtrustClient.signRaw(data, callback);
    var data = {
          "pin":"..."
    }
    client.luxtrust(reader_id).verifyPin(data, callback);
    var data = {}
    client.luxtrust(reader_id).verifyPin(data, callback);
    {
      "success": true
    }
    var data = {
      "pin": "...",
      "algorithm_reference": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.luxtrust(reader_id).authenticate(data, callback);
    var data = {
      "algorithm_reference": "sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
    }
    client.luxtrust(reader_id).authenticate(data, callback);
    {
      "success": true,
      "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
    }
    The calculated digest of the hash is prefixed with:
    DigestInfo ::= SEQUENCE {
          digestAlgorithm AlgorithmIdentifier,
          digest OCTET STRING
      }
    Make sure this has been taken into consideration in order to validate the signature in a backend process.
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      success: false,
      description: "some error description",
      code: "some error code"
    }

    Certificates

    Certificate Chain

    Extended certificates

    Root Certificate

    Authentication Certificate

    Signing Certificate

    Data Filter

    Filter Certificates

    Sign Data

    Sign Hash

    Without a pinpad reader

    With a pinpad reader

    Calculate Hash

    Raw data signing

    Trust1Connector only supports SHA2 hashing at this point.

    When using SHA3, the Trust1Connector will convert to SHA2 implicitly.

    Verify PIN

    Without a pinpad reader

    With a pinpad reader

    Authentication

    External Challenge

    Without a pinpad reader

    With a pinpad reader

    Generated Challenge

    Error Handling

    Error Object

    Core Services
    PKI.js
    calculate SHA256
    hex to base64 converter
    Status codes
    Get the EMV service:

    Call a function for the EMV container:

    The constructor for the EMV expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see . Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:

    This function call returns:

    We notice that a card object is available in the response in the context of a detected reader. The reader in the example above is VASCO DIGIPASS 870, has pin-pad capabilities, and there is a card detected with given ATR and some descriptions. An ATR (Answer To Reset) identifies the type of a smart-card. The reader, has a unique ID, reader_id; this reader_id must be used in order to request functionalities for the EMV card. This must be done upon instantiation of the EMV container:

    All methods for emv will use the selected reader - identified by the reader_id.

    List the supported applications on the EMV card

    An example callback:

    Response:

    The application data contains information of the holder of the card, the validity, the primary account number, ...

    An example callback:

    Response:

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    On some applications there is an issuer public key certificate present. The aid parameter indicates which application you want to use, this can be fetched using the applications endpoint.

    An example callback:

    Response:

    On some applications there is an icc public key certificate present. The aid parameter indicates which application you want to use, this can be fetched using the applications endpoint.

    An example callback:

    Response:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

    The following error message will be returned when PIN is wrong:

    After a second wrong PIN verification:

    Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status.

    Code

    Description

    301

    Warning: the user can try twice more to verify his PIN

    301

    Warning: the user has only 1 retry left

    The functions specified are asynchronous and always need a callback function. The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:

    The error object returned:

    For the error codes and description, see .

    export interface AbstractEmv {
        readApplicationData(callback?: (error: T1CLibException, data: PaymentReadApplicationDataResponse) => void): Promise<PaymentReadApplicationDataResponse>;
        readData(callback?: (error: T1CLibException, data: PaymentReadDataResponse) => void): Promise<PaymentReadDataResponse>;
    
        allCerts(aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: PaymentAllCertsResponse | TokenAllCertsExtendedResponse) => void): Promise<PaymentAllCertsResponse | TokenAllCertsExtendedResponse>;
        issuerPublicCertificate(aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
        iccPublicCertificate(aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
    
        allCertsExtended(aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        issuerPublicCertificateExtended(aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        iccPublicCertificateExtended(aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        verifyPin(body: PaymentVerifyPinData, callback?: (error: T1CLibException, data: PaymentVerifyPinResponse) => void): Promise<PaymentVerifyPinResponse>;
    }
    T1CSdk.initialize(config).then(res => {
    
    }, err => {
        console.error(error)
    });

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Interface

    Get EMV container object

    var emv = client.emv(reader_id);
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    emv.readData(callback)
    var coreService = client.core();
    core.readersCardAvailable(callback);
    var emv = client.emv(reader_id);
    client.emv(reader_id).readData(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      "data": [
          {
            "aid": "A0000000048002", 
            "name": "MAESTRO", 
            "priority": 1
          },{
            "aid": "A0000000048008", 
            "name": "MASTERCARD",
            "priority": 1
          }
        ],
      "success": true
    }
    client.emv(reader_id).readApplicationData(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "country": "BE",
     "countryCode": "0056",
     "effectiveDate": "190201",
     "expirationDate": "241231",
     "language": "nlen",
     "name": "",
     "pan": "670...001"
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    iccPublicCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerPublicCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,            
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "issuerPublicCertificate": {
                "certificates": [...]
            },
            "iccPublicCertificate": {
                "certificates": [...]
            }
       }
    }
    // Application ID can be retrieved with the Applications endpoint
    var aid = "..."
    
    client.emv(reader_id).issuerPublicCertificate(aid, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      "data": {
        "data": "base64 encoded data", 
        "exponent": "base64 encoded data", 
        "remainder": "base64 encoded data"
      }, 
      "success": true
    }
    // Application ID can be retrieved with the Applications endpoint
    var aid = "..."
    
    client.emv(reader_id).iccPublicCertificate(aid, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "certificate": "dxL8JnkxHneX36tdQCzz...HC3Wpt/qppk008q9OMDgVp0F7NJjCC2mXg3b/qD7c09WFXUwZ+XdkmIefhoZT/kme4QEoD49+ppQiqSeCaRjn6N0OetcjleWkPej8vE0QG4mLlG/edWTVbfMGbED9Kbjf4ooauNnq+iAVwgHedsDpdDWJLhV8sDSLQgZ1B3fMQuyZIaD79+X+H9fbhmJg+j7Lr638srglWM9VlthaWjRbFH2HzNEiQ9sOE20lmj6WM6zdYas9+Z4hcwZqWbeiTeIJDwDc6w==",
     "exponent": "AQAB",
     "remainder": ""
    }
    var data = {
        "pin": "...."
    }
    client.emv().verifyPin(data, callback);
    {
     "verified": true
    }
    var data = {}
    client.emv().verifyPin(data, callback);
    {
     "verified": true
    }
      $("#buttonValidate").on('click', function () {
          var _body={};
          _body.pin = $("#psw").val(); //only when no pin-pad available
          var emv = connector.emv(reader_id);
          emv.verifyPin(_body, validationCallback);
      });
    {
      "code": 301,
      "description": "Wrong pin, 2 tries remaining",
      "success": false
    }
    {
      "code": 301,
      "description": "Wrong pin, 1 try remaining",
      "success": false
    }
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      success: false,
      description: "some error description",
      code: "some error code"
    }

    Obtain the Reader-ID

    Reading data

    Applications

    Application data

    Extended certificates

    Issuer Public Key Certificate

    ICC Public Key Certificate

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Verify PIN - retries left

    Error Handling

    Error Object

    We notice that a card object is available in the response in the context of a detected reader. The reader in the example above is VASCO DIGIPASS 870, has pin-pad capabilities, and there is a card detected with given ATR and some descriptions. An ATR (Answer To Reset) identifies the type of a smart-card. The reader, has a unique ID, reader_id; this reader_id must be used in order to request functionalities for the Crelan card. This must be done upon instantiation of the Crelan container:

    All methods for crelan will use the selected reader - identified by the reader_id.

    List the supported applications on the Crelan card

    An example callback:

    Response:

    The application data contains information of the holder of the card, the validity, the primary account number, ...

    An example callback:

    Response:

    You can also fetch the extended versions of the certificates via the functions

    this has the capabilities to return multiple certificates if the token has multiple of this type.

    for a single certificate the response looks like:

    the allCertsExtended returns the following, with the contents of the certificates as the one you can see above;

    On some applications there is an issuer public key certificate present. The aid parameter indicates which application you want to use, this can be fetched using the applications endpoint.

    An example callback:

    Response:

    On some applications there is an icc public key certificate present. The aid parameter indicates which application you want to use, this can be fetched using the applications endpoint.

    An example callback:

    Response:

    When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

    Response:

    When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:

    Response:

    After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

    The following error message will be returned when PIN is wrong:

    After a second wrong PIN verification:

    Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status.

    Code

    Description

    301

    Warning: the user can try twice more to verify his PIN

    301

    Warning: the user has only 1 retry left

    • A Base64-encoded string representation of the digest bytes must be included in the data property of the request.

    • txId will be displayed on the PIN pad

    • language determines the language displayed on the PIN pad

    Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. The PIN will not need to re-entered until a request with bulk being set to false is sent, or the Bulk PIN Reset method is called.

    The PIN can provided/entered in the same way as Verify PIN

    Response will look like:

    The functions specified are asynchronous and always need a callback function. The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:

    The error object returned:

    For the error codes and description, see Status codes.

    export interface AbstractCrelan {
        readApplicationData(callback?: (error: T1CLibException, data: PaymentReadApplicationDataResponse) => void): Promise<PaymentReadApplicationDataResponse>;
        readData(callback?: (error: T1CLibException, data: PaymentReadDataResponse) => void): Promise<PaymentReadDataResponse>;
    
        allCerts(aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: PaymentAllCertsResponse | TokenAllCertsExtendedResponse) => void): Promise<PaymentAllCertsResponse | TokenAllCertsExtendedResponse>;
        issuerPublicCertificate(aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
        iccPublicCertificate(aid: string, callback?: (error: T1CLibException, data: PaymentCertificateResponse) => void): Promise<PaymentCertificateResponse>;
    
        allCertsExtended(aid: string, filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
        issuerPublicCertificateExtended(aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
        iccPublicCertificateExtended(aid: string, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    
        verifyPin(body: PaymentVerifyPinData, callback?: (error: T1CLibException, data: PaymentVerifyPinResponse) => void): Promise<PaymentVerifyPinResponse>;
        sign(body: PaymentSignData, bulk?: boolean, callback?: (error: T1CLibException, data: PaymentSignResponse) => void): Promise<PaymentSignResponse>;
        resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    }
    T1CSdk.T1CClient.initialize(config).then(res => {
      client = res;
    }, err => {
        console.error(error)
    });
    var crelan = client.crelan(reader_id);
    function callback(err,data) {
        if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
        else {console.log(JSON.stringify(data, null, '  '));}
    }
    crelan.readData(callback)
    var coreService = client.core();
    core.readersCardAvailable(callback);

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    Interface

    Get Crelan Module

    Obtain the Reader-ID

    Core Services
    var crelan = client.crelan(reader_id);
    client.crelan(reader_id).readData(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      "data": [
          {
            "aid": "A0000000048002", 
            "name": "MAESTRO", 
            "priority": 1
          },{
            "aid": "A0000000048008", 
            "name": "MASTERCARD",
            "priority": 1
          }
        ],
      "success": true
    }
    client.crelan(reader_id).readApplicationData(callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "country": "BE",
     "countryCode": "0056",
     "effectiveDate": "190201",
     "expirationDate": "241231",
     "language": "nlen",
     "name": "",
     "pan": "670...001"
    }
    allCertsExtended(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsExtendedResponse) => void): Promise<TokenAllCertsExtendedResponse>;
    iccPublicCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    issuerPublicCertificateExtended(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateExtendedResponse) => void): Promise<TokenCertificateExtendedResponse>;
    {
        "success" : true
        "data" : {
            "certificates": [{
                "certificate"?: string,            
                "exponent"?: string,
                "remainder"?: string,
                "parsedCertificate"?: Certificate
            }]
        }
    }
    {
        "success" : true
        "data" : {
            "issuerPublicCertificate": {
                "certificates": [...]
            },
            "iccPublicCertificate": {
                "certificates": [...]
            }
       }
    }
    // Application ID can be retrieved with the Applications endpoint
    var aid = "..."
    
    client.crelan(reader_id).issuerPublicCertificate(aid, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      "data": {
        "data": "base64 encoded data", 
        "exponent": "base64 encoded data", 
        "remainder": "base64 encoded data"
      }, 
      "success": true
    }
    // Application ID can be retrieved with the Applications endpoint
    var aid = "..."
    
    client.c(reader_id).iccPublicCertificate(aid, callback);
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
     "certificate": "dxL8JnkxHneX36tdQCzz...HC3Wpt/qppk008q9OMDgVp0F7NJjCC2mXg3b/qD7c09WFXUwZ+XdkmIefhoZT/kme4QEoD49+ppQiqSeCaRjn6N0OetcjleWkPej8vE0QG4mLlG/edWTVbfMGbED9Kbjf4ooauNnq+iAVwgHedsDpdDWJLhV8sDSLQgZ1B3fMQuyZIaD79+X+H9fbhmJg+j7Lr638srglWM9VlthaWjRbFH2HzNEiQ9sOE20lmj6WM6zdYas9+Z4hcwZqWbeiTeIJDwDc6w==",
     "exponent": "AQAB",
     "remainder": ""
    }
    var data = {
        "pin": "...."
    }
    client.crelan(reader_id).verifyPin(data, callback);
    {
     "verified": true
    }
    var data = {}
    client.crelan(reader_id).verifyPin(data, callback);
    {
     "verified": true
    }
      $("#buttonValidate").on('click', function () {
          var _body={};
          _body.pin = $("#psw").val(); //only when no pin-pad available
          var crelan = connector.crelan(reader_id);
          crelan.verifyPin(_body, validationCallback);
      });
    {
      "code": 301,
      "description": "Wrong pin, 2 tries remaining",
      "success": false
    }
    {
      "code": 301,
      "description": "Wrong pin, 1 try remaining",
      "success": false
    }
    const data = {
        txId: "Tx1",
        data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
        language: "fr"
    }
    const bulk = false;
    crelan.sign(data, bulk).then(res => {
    }, err => {
        console.error(err)
    })
    {
        "success": true,
        "data": {
          "data": "..."
          "cardSignature": "...",
          "readerSignature": "...",
        }    
    }
    function callback(err,data) {
        if(err){
            console.log("Error:",JSON.stringify(err, null, '  '));
        }
        else {
            console.log(JSON.stringify(data, null, '  '));
        }
    }
    {
      success: false,
      description: "some error description",
      code: "some error code"
    }

    Reading data

    Applications

    Application data

    Extended certificates

    Issuer Public Key Certificate

    ICC Public Key Certificate

    Verify PIN

    Verify PIN without pin-pad

    Verify PIN with pin-pad

    Verify PIN - retries left

    Sign

    When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.

    Error Handling

    Error Object

    Core Services
    Status codes

    File exchange

    File management, file up and download using an operating system abstraction layer. Allows the consuming application to work with OS independent directory and file aliases.

    Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.

    Introduction

    The File Exchange container allows Trust1Connector to manage files and directories, to upload or download files to/from the filesystem from/to the requesting party (especially for web application). The user of the device must give a consent prior of file operations.

    The File Exchange container provides the following functionalities:

    • selecting a folder based on application type

    • listing files in selected application type

    • downloading one or more files into selected application type

    • uploading one or more files from the selected application type

    • creating sub directories in 'mapped' folders (application types)

    The Trust1Connector does NOT allow the deletion of folders or files residing on the user's device.

    An application type resolves locally to an absolute file system path.

    An application can create additional folders for a given application type, those folders are relative to the absolute path which has been locally mapped on the application type. This means that the web application can ask the user to create subdirectories in an application type which has been already mapped.

    The File Exchange container provides additionally:

    • optional user notification for file transfer completion

    • copy and move files between application types

    • user consent to allow the consuming application to perform file operations

    The configuration file can be found in

    The File Exchange container allows the application to choose whether to notify the users in the application context, or to delegate notification to the T1C. The T1C uses the underlying operating system to notify users. The type of notification supported by the T1C is system modal information (message, error, warning dialogs).

    The context of a type mapping is defined by the following concepts:

    • application_id (property of Type class): a string value denoting the application identifier. This is the root context for entity mapping. The application id is derived from the Origin domain and acts as an application scope for all defined mappings

    • entity: a string value denoting the root entity/owner for types mapping. This can be called the root for al 'aliases' or 'type mappings' which will be created.

    • type: a string value denoting a file typing, related to the absolute path mapped by an user; this value abstracts absolute paths from an application perspective as it acts as an alias, referencing a file or directory based on the configured absolute path.

    The following image depicts the file exchange object model:

    A 'Type' in the context of the File Exchange container, is an alias or label, used by an application, to abstract the absolute path reference of the local file system. A 'Type' allows the application to perform file transfers, without the notion of the local file system organisation. The File Exchange container maps the absolute path, chosen by a user, on the application scoped label. We call this action a 'type mapping', this is, an absolute path, in the context of an application, is references by an alias or label (=Type).

    A conceptual example, a mapping of

    can be mapped on:

    When the example mapping has been done, the consuming application does not need to worry about the underlying operating system, and can just target the folder or file using the tuple (entity, type) bounded implicitly by the operating domain (mywebapp.com).

    Subfolders can be managed by the application. All subfolder are relative paths and when requested can be created, optionally recursively, by the File Exchange API. It's important to understand:

    • Type mapping : correlates to absolute paths on a local file system

    • Type subfolders: correlates to relative paths on a local file system and MUST reside in a type mapping/definition.

    The File Exchange container maintains the mapping for absolute paths. Relative paths will be created when used in the specified use case. Neither absolute paths or relative paths will result in deletion on the local file system! When deleting a 'type' (aka absolute path), the type will be removed from the File Exchange container, but the references directory will still exist on the user's file system.

    In the File Exchange API, the parameter relpath refers to an array of strings denoting a directory path, within a type mapping.

    The File Exchange API can be integrated using Promises or callbacks. Both are returning the same result.

    The File Exchange container allows for bulk file transfer. The individual methods are stateless requests to the T1C-GCL service, and allows to up- or download one or more files from a user perspective. The progress information can be retrieved by the application for each file separately or for all the actions running on the T1C-GCL service.

    The language, used for OS modals, is determined the web application. The title and message properties can be provided, which will be used in the underlying OS modal/dialog. For OSX, there is no title of message for the file or directory chooser. In OSX you can only pass through the title and message using system modals (error, warn, info messages and PIN dialog).

    The following enumerators have been exported by the File Exchange container:

    The following functions are available in the T1C-JS library:

    The File Exchange container uses paging for the endpoints:

    • listTypes

    • listContent

    The page-parameter can be optionally provided and contains the following properties:

    • start: start index

    • size: number of items on a page

    • sort: ordering of file and directory names ascending or descending

    When used, the resulting response returns an 'total' property with the total item count for the requested resource.

    Creates a file named filename at the type location in the context of entity, optionally in relative folder denoted by relpath, with file content file. Optionally notifies user upon completion.. When notifications are disabled, the application is assumed to handle user notifications.

    The optional relpath provided, will be created when not existing, this in a recursive manner.

    • entity: the entity context where the type mapping is persisted

    • type: location for the newly created file

    • file: Blob containing binary data to be put in the file

    The use cases are the followings with the concerned parameters :

    Use Case 1

    • download with existing Type (whatever the value true or false of the flag ‘implicitCreationType’)

      • The user launches the download process with a relpath.

      • The application uses the T1C function download with as parameter a relpath.

    Use Case 2 – download with non existing Type and parameter ‘implicitCreationType’ = false

    • The user launches the download process.

    • The application uses the T1C function download with as parameter a relpath.

    • The exception 356 is raised due the fact the Type doesn’t exist.

    Use Case 3 – download with non existing Type and parameter ‘implicitCreationType’ = true

    • The user launches the download process.

    • The application uses the T1C function download with as parameter a relpath.

    • The user will see the prompt for the Type creation with a default path.

    Uploads a file named filename, from the type location, optionally in relative folder denoted with relpath. Optionally notifies the user upon completion.. When the notifications are disabled, the application is assumed to handle user notifications.

    The optional relpath provided, will be created when not existing, this in a recursive manner.

    • entity: the entity context where the type mapping is persisted

    • type: location for the file to upload

    • filename: name of the file to be uploaded

    Returns a Blob object

    Retrieve a list of current persisted mappings given an optional entity.

    • entity: the entity context where the type mapping is persisted. Optional.

    • page: apply a paging to the result. Optional.

    Retrieve a list of current mappings given an entity type context.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    List all the content for a mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • relpath: specify a relative path to retrieve the files

    List all the content for a mapping given an entity context..

    • entity: the entity context where the type mapping is persisted.

    • page: apply a paging to the result. Optional.

    Verify if a context mapping exists.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    Verify if a file exists in a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • relpath: a relative path based on the context root folder

    Get the access mode of a folder or file in a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • filename: an optional filename, if not specified the folder access mode will be returned

    Create a directory in a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • relpath: a relative path based on the context root folder

    Copy a file from one context mapping to another.

    • entity: the entity context where the type mapping is persisted.

    • fromType: the originating entity type mapping context

    • toType: the destination entity type mapping context

    Move a file from one context mapping to another.

    • entity: the entity context where the type mapping is persisted.

    • fromType: the originating entity type mapping context

    • toType: the destination entity type mapping context

    Rename a file in a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • fromType: the originating entity type mapping context

    • toType: the destination entity type mapping context

    Get file information of a file in a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the originating entity type mapping context

    • filename: the name the of the to copy

    The initPath parameter denotes an initial path proposal from the application. Example values:

    The optional parameter modal is by default set to true.

    When createType is called upon an existing type mapping, the file-chooser shown to the user is defaults to the existing absolute path provided for the type.

    The showModal flag is used to propose (or not) the prompt to the end user even if the initPath exists or not. This parameter forces the prompt of the file chooser:

    • when the initPath is provided and showModal is set to true: the initPath is pre-selected in the file-chooser shown to the user if existing, or the file-chooser is shown with a default path.

    • when the initPath is provided and modal is set to false: the initabspath

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • modal: indicate if the folder dialog must be shown

    The use cases are the followings with the concerned parameters:

    Use Case 1

    • createType with an existing initPath and parameter showModal = true

      • The user will create a type mapping.

    Create directories for a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • relpath: a relative path based on the context root folder

    Update a context mapping. A folder dialog will be opened and a new root context path can be choosen.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    • timeout: timeout in seconds before the folder dialog is discarded)

    Delete a context mapping.

    • entity: the entity context where the type mapping is persisted.

    • type: the entity type mapping context

    The error codes mentioned are added to the File Exchange container. The exception handling follows the framework exception handling and are extensions of status codes mentioned on:

    Changing Device date/time

    Issues related to device time not in sync

    The connector can only work when the device date/time is correctly set. This is due to the security applied on exchanged tokens and keys.

    When a connector has been installed on a device, at a moment which is in the past (other day/time), this results in the connector not working, even though the date/time has been set correctly on the system (post-installation).

    To solve this problem the followin steps need to be executed:

    • remove all device related keys

    301

    Error: the PIN is blocked

    301

    Error: the PIN is blocked

    Core Services
    Status codes
    application/domain scoped, application types are bound to the application domain
  • OS native files and directory chooser dialogs

  • Use to inform the application if a Type has been mapped to an absolute path by the user.

    upload

    entity, type, filename, relpath, notifyOnCompletion

    array buffer

    Uploads a file named filename, from the type location, optionally in relative folder denoted with relpath. Optionally notifies user upon completion.

    listTypes

    entity, page

    list of type objects

    Returns a list of existing types. The type object contains information about the mapping of absolute paths. Paging can be used optionally by using the page parameter.

    listType

    entity, type

    type object

    Returns the targeted type object.

    listTypeContent

    entity, type, relpath, page

    list of file objects

    Returns a list of file objects for the targeted type. A file can be a directory or a binary file. The relpath refers to the directory path where files should be searched for.

    listContent

    entity, page

    list of file objects

    Returns a list of file objects for all known types. The list will contain all files that are present in defined types.

    existsType

    entity, type

    boolean

    Verifies if type exists. Be aware that a type can exist, but no mapping has been persisted by the user.

    existsFile

    entity, type, relpath

    boolean

    Verifies if a file exists on the local file system.

    getAccessMode

    entity, type, relpath, filename

    access mode

    Returns the access mode for a file or directory. The param relpath can be used to target a nested file or directory.

    createDir

    entity, type, relpath, recursive

    file object

    Returns the created file object (which in this use case is always a directory). When recursive is set to true, the all subfolders will be created.

    copyFile

    entity, fromType, toType, filename, newfilename, fromrelpath, torelpath

    file object

    Copy a file or directory on the local file system.

    moveFile

    entity, fromType, toType, filename, fromrelpath, torelpath

    file object

    Move a file or directory on the local file system.

    renameFile

    entity, type, filename, newfilename, relpath

    file object

    Rename a file or directory

    getFileInfo

    entity, type, filename, relpath

    file object

    Returns the targeted file information

    createType

    entity, type, timeoutInSeconds, initabspath

    type object

    Creates a new type mapping, with optional initial path (migration support). When the path is not found on the local system, the user will be prompted with a file chooser.

    createTypeDirs

    entity, type, relpath, showModal, timeoutInSeconds

    type object

    Creates new subfolders for a type mapping. If the type mapping is not existing, the user will be prompted with a file chooser.

    updateType

    entity, type, timeoutInSeconds

    type object

    Prompt the user to force renewal of type mapping. The user will be presented with file chooser, even when the mapping exists already.

    deleteType

    entity, type

    boolean

    Removes the type mapping, but does not delete

    directories or files from the local system.

    filename: name to be given to the file

  • relpath: optional relative path (array of strings), when provided will implicitly create the missing directories.

  • implicitCreationType: In case the type mapping doesn’t exist, a prompt will be shown to the user for creating the Type before performing the download.

  • notifyOnCompletion: show modal info form operating system to user upon completion

  • The file is downloaded to the directory of the path + relpath (recursive creation).

    End
    The user selects the directory and cancels or validates the creation:
    • Cancellation of the creation.

    • Validation of the creation.

      • The Type is created.

      • The file is downloaded to the directory of the path + relpath (recursive creation).

    relpath: optional relative path (array of strings)
  • notifyOnCompletion: show modal info form operating system to user upon completion

  • page: apply a paging to the result. Optional.

    relpath: an optional relative path based on the context root folder

    recursive: indicate whether the directory should be created recursively. If not and the parent directories do not exist, an error will be thrown.

    filename: the name the of the to copy

  • newfilename: the new destination file name

  • fromrelpath: an optional originating relative path based on the context root folder

  • torelpath: an optional destination relative path based on the context root folder

  • filename: the name the of the to copy

  • fromrelpath: an optional originating relative path based on the context root folder

  • torelpath: an optional destination relative path based on the context root folder

  • filename: the name the of the to copy

  • relpath: an optional relative path based on the context root folder

  • relpath: an optional relative path based on the context root folder

    is used when mapping exists, otherwise the file-chooser is shown to the user in order to select a valid absolute path.
  • when the initPath is not provided and modal is set to true: the file-chooser is shown when the mapping doesn't exist.

  • when the initPath is not provided and modal is set to false: a type exception is thrown when the type mapping doesn't exist

  • timeout: optional timeout in seconds before the folder dialog is discarded)

  • initPath: the optional initial root context path for the new type

  • The application uses the T1C function createType with as parameter an existing initabspath and the modal set to true.
  • A prompt must appear with the value set to initPath.

  • The user selects (or not) a directory and cancels or validates the creation:

  • Cancellation of the creation.

    • The exception is raised due the fact it has been aborted.

  • Validation of the creation.

    • The Type is created.

  • End

  • Use Case 2

    • createType with an existing initabspath and parameter modal = false

      • The user will create a Type

    • The application uses the T1C function createType using as parameter an existing initPath and the modal set to false.

    • No prompt will be proposed to the end user but the Type is created.

    • End

  • Use Case 3

    • createType with a non existing initPath (whatever the value true or false of the flag modal)

      • The user will create a Type.

    • The application uses the T1C function createType with as parameter a non existing initPath.

    • A prompt must appear with default value.

    • The user selects (or not) a directory and cancels or validates the creation:

      • Cancellation of the creation.

        • The exception is raised due the fact it has been aborted.

    • End

  • modal: indicate if the folder dialog must be shown

  • timeout: optional timeout in seconds before the folder dialog is discarded)

  • %localappdata%\Trust1Connector\file-exchange.json
    [Windows]
    "C:\Users\userA\t1t\coda"
    [OSX]
    "/Users/userA/t1t/coda"
    application_id: mywebapp.com //domain
    entity: Trust1Team //root context
    type: Coda
    interface AbstractFileExchange {
        download(entity: string, type: string, file: Blob, fileName: string, relPath?: [string], implicitCreationType?: boolean, notifyOnCompletion?: boolean, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<DataResponse>;
        upload(entity: string, type: string, fileName: string, rel_path?: [string], notifyOnCompletion?: boolean, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<Blob>;
        listTypes(entity?: string, page?: Page, callback?: (error: T1CLibException, data: TypeListResponse) => void): Promise<TypeListResponse>;
        listType(entity: string, type: string, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
        listTypeContent(entity: string, type: string, relPath?: [string], page?: Page, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
        listContent(entity: string, page?: Page, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
        existsType(entity: string, type: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        existsFile(entity: string, type: string, relPath: [string], callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
        getAccessMode(entity: string, type: string, relPath?: [string], callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
        createDir(entity: string, type: string, relPath: [string], recursive?: boolean, callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
        copyFile(entity: string, fromType: string, toType: string, fileName: string, newfileName: string, fromrelPath?: [string], toRelPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
        moveFile(entity: string, fromType: string, toType: string, fileName: string, fromrelPath?: [string], toRelPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
        renameFile(entity: string, type: string, fileName: string, newfileName: string, relPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
        getFileInfo(entity: string, type: string, fileName: string, relPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
        createType(entity: string, type: string, initPath?: [string], modal?: boolean, timeout?: number, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
        createTypeDirs(entity: string, type: string, rel_path: [string], modal?: boolean, timeout?: number, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
        updateType(entity: string, type: string, timeout?: number, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
        deleteType(entity: string, type: string, callback?: (error: T1CLibException, data: boolean) => void): Promise<boolean>;
    }
    enum FileSort {ASC, DESC}
    enum TypeStatus {MAPPED,UNMAPPED}

    Enum

    Values

    Description

    FileSort

    ASC, DESC

    Used for sorting files. ASC = ascending, DESC = descending

    TypeStatus

    class T1CResponse {
        constructor(public success: boolean, public data?: any) {}
    }
    
    class ListFilesRequest {
        constructor(public path: string, public extensions: string[]) {}
    }
    
    export class File {
        constructor(public extension: string,
                    public name: string,
                    public path: string,
                    public relPath: string[],
                    public type: string,
                    public entity: string,
                    public size: number,
                    public lastModificationTime: string,
                    public isDir: boolean,
                    public access: string) {}
    }
    
    class FileListResponse extends T1CResponse {
        constructor(public data: FileList, public success: boolean) {
        super(success, data);
        }
    }
    
    class FileList {
        constructor(public files: File[], public total: number) {}
    }
    
    class FileResponse extends T1CResponse {
        constructor(public data: File, public success: boolean) {
            super(success, data);
        }
    }
    
    class TypeListResponse extends T1CResponse {
        constructor(public data: TypeList, public success: boolean) {
            super(success, data);
        }
    }
    
    class TypeResponse extends T1CResponse {
        constructor(public data: Type, public success: boolean){
            super(success, data);
        }
    }
    
    class Type {
        constructor(public entity: string, public type: string, public path: string, access: string, status: TypeStatus, public files: number, public appid?: string) {}
    }
    
    class TypeList{
        constructor(public types: Type[], public total: number) {}
    }
    
    class Page {
        constructor (public start: number, public size: number, public sort: FileSort) {}
    }
    
    class DataArrayResponse extends T1CResponse {
        constructor(public data: string[], public success: boolean) {
            super(success, data);
        }
    }
    
    class DataResponse extends T1CResponse {
        constructor(public data: string, public success: boolean) {
            super(success, data);
        }
    }
    
    class RestException {
        constructor(public status: number, public code: string, public description: string, public client?: GCLClient) {
            ObjectUtil.removeNullAndUndefinedFields(this);
        }
    }
    

    JavaScript API

    Function

    Input

    Output

    Description

    download

    entity, type, file, filename, relpath, implicitCreationType, notifyOnCompletion

    success value

    Creates a file named filename at the type location, optionally in relative folder denoted by relpath, with file contents file. Optionally notifies user upon completion.

    download(entity: string, type: string, file: Blob, fileName: string, relPath?: [string], implicitCreationType?: boolean, notifyOnCompletion?: boolean, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<DataResponse>;
    {
        data: string
        success: boolean
    }
    upload(entity: string, type: string, fileName: string, relPath?: [string], notifyOnCompletion?: boolean, callback?: (error: T1CLibException, data: Blob) => void): Promise<Blob>;
    listTypes(entity?: string, page?: Page, callback?: (error: T1CLibException, data: TypeListResponse) => void): Promise<TypeListResponse>;
    {
        data: TypeList
        success: boolean
    }
    listType(entity: string, type: string, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
    {
        data: Type
        success: boolean
    }
    listTypeContent(entity: string, type: string, relPath?: [string], page?: Page, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
    {
        data: FileList
        success: boolean
    }
    listContent(entity: string, page?: Page, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
    {
        data: FileList
        success: boolean
    }
    existsType(entity: string, type: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    {
        data: boolean
        success: boolean
    }
    existsFile(entity: string, type: string, relPath: [string], callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
    {
        data: boolean
        success: boolean
    }
    getAccessMode(entity: string, type: string, fileName: string, relPath?: [string], callback?: (error: T1CLibException, data: DataResponse) => void): Promise<DataResponse>;
    {
        data: string ("rwx")
        success: boolean
    }
    createDir(entity: string, type: string, relPath: [string], recursive?: boolean, callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
    {
        data: File
        success: boolean
    }
    copyFile(entity: string, fromType: string, toType: string, fileName: string, newfileName: string, fromrelPath?: [string], toRelPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
    {
        data: File
        success: boolean
    }
    moveFile(entity: string, fromType: string, toType: string, fileName: string, fromrelPath?: [string], toRelPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
    {
        data: File
        success: boolean
    }
    renameFile(entity: string, type: string, fileName: string, newfileName: string, relPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
    {
        data: File
        success: boolean
    }
    getFileInfo(entity: string, type: string, fileName: string, relPath?: [string], callback?: (error: T1CLibException, data: FileResponse) => void): Promise<FileResponse>;
    {
        data: File
        success: boolean
    }
    inittabspath = [ "C:\", "Users", "user1", "Desktop", "folder1" ];
    inittabspath = [ "C:\Users", "user1", "Desktop", "folder1" ];
    inittabspath = [ "C:\Users\user1\Desktop\folder1" ];
    initPath = [ "Users", "user1", "Desktop", "folder1" ];
    initPath = [ "/Users/user1/Desktop/folder1" ];
    initPath = [ "home", "user1", "Desktop", "folder1" ];
    initPath = [ "/home/user1/Desktop/folder1" ];
    createType(entity: string, type: string, initPath: [string], modal?: boolean, timeout?: number, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
    {
        data: Type
        success: boolean
    }
    createTypeDirs(entity: string, type: string, relPath: [string], modal?: boolean, timeout?: number, callback?: (error: T1CLibException, data: FileListResponse) => void): Promise<FileListResponse>;
    {
        data: FileList
        success: boolean
    }
    updateType(entity: string, type: string, timeout?: number, callback?: (error: T1CLibException, data: TypeResponse) => void): Promise<TypeResponse>;
    {
        data: Type
        success: boolean
    }
    deleteType(entity: string, type: string, callback?: (error: T1CLibException, data: boolean) => void): Promise<boolean>;
    {
        data: boolean
        success: boolean
    }

    The File-exchange payload limit is set to 50 MB. If your needs exceed this please contact support

    Configuration file

    Notifications

    Context and scope

    Type Mapping

    Type subfolders

    Responses

    Bulk File Transfer

    Language

    Interface

    Objects

    Enums

    Classes

    Function Descriptions

    Detailed Function Overview

    Paging (Page interface)

    download

    Interface

    Parameters

    Output

    Use Cases

    upload

    Interface

    Parameters

    Output

    listTypes

    Interface

    Parameters

    Output

    listType

    Interface

    Parameters

    Output

    listTypeContent

    Interface

    Parameters

    Output

    listContent

    Interface

    Parameters

    Output

    existsType

    Interface

    Parameters

    Output

    existsFile

    Interface

    Parameters

    Output

    getAccessMode

    Interface

    Parameters

    Output

    createDir

    Interface

    Parameters

    Output

    copyFile

    Interface

    Parameters

    Output

    moveFile

    Interface

    Parameters

    Output

    renameFile

    Interface

    Parameters

    Output

    getFileInfo

    Interface

    Parameters

    Output

    createType

    Windows

    macOS

    Linux

    Interface

    Parameters

    Output

    Use Cases

    createTypeDirs

    Interface

    Parameters

    Output

    updateType

    Interface

    Parameters

    Output

    deleteType

    Interface

    Parameters

    Output

    Error Responses

    Status codes / error handeling
    File Exchange Object Model

    MAPPED, UNMAPPED

    restart the connector

    Go to the installation folder of the connector:

    %localappdata%/Trust1Connector

    Delete all security relate files (selected below):

    Those files are:

    • device.priv

    • device.pub

    • device_der.priv

    • device_der.pub

    • device_x509_der.pub

    • ds-ssl.json

    • ds-txs.bck

    Restart the connector by executing the 't1c-launch'

    The process will be stopped, and restarted. The 't1c-launch' process must stop running, and the new processes will trigger the re-generation of the new keys.

    Due to this action, the device performs a new registration to the Distribution service, this can be verified in the api.log file (in the /Logs folder)

    Go to the installation folder of the connector:

    cd ~/Library/Application\ Support/Trust1Team/Trust1Connector/

    Open the folder in finder:

    open .

    Delete all security relate files (selected below):

    Those files are:

    • device.priv

    • device.pub

    • device_der.priv

    • device_der.pub

    • device_x509_der.pub

    • ds-ssl.json

    • ds-txs.bck

    Use the terminal to open the connector installation folder:

    cd ~/Library/Application\ Support/Trust1Team/Trust1Connector

    Execute the t1c-launch to restart

    ./t1c-launch --restart

    The process will be stopped, and restarted. The 't1c-launch' process must stop running, and the new processes will trigger the re-generation of the new keys.

    Due to this action, the device performs a new registration to the Distribution service, this can be verified in the api.log file (in the /Logs folder)

    Introduction

    Solution

    Windows

    Those files will be automatically generated by the connector after the next step

    Mac OSX

    Those files will be automatically generated by the connector after the next step

    Mac OSX Sonoma and higher

    Smart Card Reader Issues Tracker for Sonoma

    Issue installation after reboot

    On MacOS we make use of the launchd service to automatically start the Trust1Connector upon startup of the machine. In some cases where users have installed certain antivirus or anti-malware software it will prevent launched services to startup immediately. The reason here being that the anti-malware or antivirus software should be the first that start up so it can controll the launchd services.

    In this case the Trust1Connector will not be started and will receive an error on the launchd.

    This can be solved to add a KeepAlive flag in the launchd service.

    Update the launchd plist file

    Go to the LaunchAgents folder and unload the Trust1Connector service

    cd ~/Library/LaunchAgents
    launchctl unload com.t1t.t1c.api.plist

    Then open this plist file in a text editor and add the keepalive flag under the RunAtLoad flag.

    ...
     <key>RunAtLoad</key>
     <true/>
     <key>KeepAlive</key>
     <true/>
    ...

    Then save this and reload the service

    after this you should restart your computer.

    A short fix for Mac Sonoma, more details below in the section 'Overview'.

    Execute the following steps:

    1. Open a Mac Terminal

    2. Execute command: sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool yes

    3. Unplug smart card reader from USB port

    4. Restart Mac

    The fix has been applied and you should be able to sign a document or authenticate

    Starting from OSX Sonoma, smart card readers for Mac can fail for the following use cases:

    • detect card reader

    • execute transaction (digital signature or authentication)

    The general end-user experience is that the smart card communication fails (card reader disseappears or the transaction fails).

    A very great shout-out to Ludovic Rousseau who initially did a follow-up on impact of smart card readers in Sonoma:

    The initial solution prior to 11/2023 was very elaborate, but was made easy by applying a single command in a MAC OSX terminal:

    The command switches the MAC OSX implementation of the CCID drivers to the legacy version (the version working prior to Sonoma).

    As MAC OSX defaults using a custom CCID implementation, which still have some issues, switching to the old version is a temporary stolution.

    Form a specific moment (not at the time of writing), switching back to the default CCID implementation can be done using the following commands (in a terminal):

    Check if the built-in Apple CCID driver is active

    If the former command results in:

    This means that the built-in Apple driver is active.

    The result is 1 so the "external" (non-Apple) CCID driver is enabled.

    Returning back to default, execute:

    Windows dynamic port range

    The Trust1Connector is using 3 different network ports for communication, For the Trust1Connector by Trust1Team these are ;

    • Registry, fixed 51983 (51883 for the acceptance version)

    • API, dynamically assigned

    Troubleshooting

    In some cases the Support Desk will ask for a HAR file. This means an export of the functions that a web-page is executing. This is to see that all the functions that call the Trust1Connector are executed correctly.

    Before you use the web application open the developer tools. This can be done by right clicking and click on inspect

    This will open a window like this

    Next navigate to the network tab in the inspect

    Windows

    When your windows machine has Windows hello for business available it will show up as an available card reader. This device shows up as an available card but cannot be interacted with like other card readers.

    You can exclude this from returning on the reader endpoints by using the readersExcludeByName function

    Open Explorer, and go to %localappdata% or (C:\Users\xyz\AppData\Local\Trust1Connector)

    Double click (launch) the .exe file: 't1c-launch'.

    If you see the following:

    Then you need to make sure that VCRuntime is installed for Windows. You can find the latest versions here:

    Validation of the creation.

    • The Type is created.

  • Plug smart card reader back in USB port

  • launchctl load com.t1t.t1c.api.plist
    sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool yes
    defaults read /Library/Preferences/com.apple.security.smartcard.plist useIFDCCID
    he domain/default pair of (/Library/Preferences/com.apple.security.smartcard.plist, useIFDCCID) does not exist
    sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool no

    Smart-card issue

    Quick fix

    Overview

    Reported Bug to Mac OSX:

    OSX Forum

    Solution

    What does the command execute/change?

    How to roll-back to MAC OSX CCID implementation?

    After executing a driver switch, we have noticed that a restart is mandatory!

    You need to unplug your smart card reader from the USB port, and plug it back in after restarting

    Sandbox, dynamically assigned

    In some rare cases the windows system prevents a range of TCP ports to be used by applications, this is called an exclusion range.

    You can see the dynamic port range by executing the following command in a terminal

    The output will look like the following

    For the exclusion range you can use the following command

    This can look like the following, this can differ from your system

    To remove the listed port ranges from the exclusion range you can use the following command.

    This will make sure that starting of 51980 there are 10 ports allowed to be used by other applications.

    If the steps above did not solve your issue you can also update the dynamic port range with the following command. This will move the port range to start from 54000 and have 10511 available ports to be used.

    netsh int ipv4 show dynamicport tcp
    Protocol tcp Dynamic Port Range
    ---------------------------------
    Start Port      : 49152
    Number of Ports : 16384
    netsh interface ipv4 show excludedportrange protocol=tcp
    Protocol tcp Port Exclusion Ranges
    
    Start Port    End Port
    ----------    --------
         53180       53189     *
    
    * - Administered port exclusions.
    netsh int ipv4 delete excludedportrange protocol=tcp startport=51980 numberofports=10
    netsh int ipv4 set dynamic tcp start=54000 num=10511

    In some cases you will need to stop winnat before having access to the exclusion range

    After updating the exclusion range you need to restart winnat

    window

    When this is done, use the web application's functionality and when you are finished or come to an issue you can use the download button to get a HAR file, save the file to your system and send this to the Support Desk

    The Smartcard service is a Windows service that manages the connection to the eID and card reader. Therefore, this service must be running for you to be able to access the eID. You can check this as follows:

    • Open "Windows Services".

    • Search for "Smartcard service" as shown in the following screenshot:

    Check the following Smartcard service settings (based on the screenshot above):

    • The status column for the Smartcard service shows 'Running'.

    • The 'Log On As' column shows 'Local Service'.

    Are the Smartcard service settings NOT as they should be? Then do whichever of the following two options applies:

    1. The Smartcard service is not running.

    Start the Smartcard service, as follows:

    • Double-click the Smartcard service.

    • Click 'Start' and then 'OK'.

    2. The Smartcard service is not logged on as a 'Local Service'.

    • Double-click the Smartcard service.

    • Select the second tab, 'Log On'.

    • Select 'This account'.

    • Click 'Browse'.

    • In the white text box, type: loc.

    • Then click 'Check names'.

    • The name 'Local service' now appears in the text box.

    • Then click 'OK'.

    • Leave the password boxes empty.

    • Click 'Apply'.

    • Click 'OK'.

    • Go back to the first tab, 'General', and restart the service.

    • Click 'Start'.

    • Click 'Stop'.

    In some cases there is a possibility that the system is not able to retrieve the domain information, in this case the T1C is not usable. To solve this problem you can follow these steps described here; https://www.hostinger.com/tutorials/fix-dns_probe_finished_nxdomain

    When installing the T1C the possibility of the errors 2502 or 2503 originate from the fact that permissions in the temp folder (C:\Windows\Temp) are not correct, and since the MSI installer relies on this they need to be correct. You need to have permissions next to the administrator rights.

    You need to have permissions as <My User> next to the administrator rights.

    More information can be found here; https://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/windows-8-install-some-software-using-msi/48881523-1a5d-4c43-abc4-01b1ce3ebf3a

    The Trust1Connector and some installation files are digitally signed. On some machines however the Trust1Connector is flagged/blocked by an antivirus. Disabling the antivirus temporary can allow the user to install the Trust1Connector for some antivirus tools. Below we provide procedures for some antivirus softwares to be able to install the Trust1Connector.

    If the user receives an notification that a script from the Trust1Connector is blocked as shown below:

    The procedure at https://support.eset.com/kb2908/?locale=en_US&viewlocale=en_US can be used to solved the issue.

    When using the Kaspersky and kaspersky web protection you can add an exclusion rule to the belfiusweb page. After you added this rule, restart the computer to make sure all settings are applied.

    If the connector is not starting with the error message: "Can not contact the DS service"

    Go to the user folder in %LocalAppData%

    Go to BelfiusConnector folder and remove the selected files below:

    Restart your pc or mac, and the restart will re-initialise the device keys.

    The problem should be solved after executing this step.

    Generating a HAR file for support

    Windows

    Error while retrieving readers

    Is the smartcard service running?

    DNS probe finished nxdomain error

    Error during installation MSI error 2502 or 2503

    Antivirus

    ESET

    Kaspersky

    A9. T1C List Type Conent Issue

    Checking whether the VC runtime is installed can be done via the file explorer or via regedit.

    For the file explorer you need to check if the following file is present

    Via regedit you need to check for the following key

    See the dedicated section on how to sovle DNS Rebing:

    Connector Connection Issues

    The Smartcard service is a Windows service that manages the connection to the eID and card reader. Therefore, this service must be running for you to be able to access the eID. You can check this as follows:

    • Open "Windows Services".

    • Search for "Smartcard service" as shown in the following screenshot:

    Check the following Smartcard service settings (based on the screenshot above):

    • The status column for the Smartcard service shows 'Running'.

    • The 'Log On As' column shows 'Local Service'.

    Are the Smartcard service settings NOT as they should be? Then do whichever of the following two options applies:

    1. The Smartcard service is not running.

    Start the Smartcard service, as follows:

    • Double-click the Smartcard service.

    • Click 'Start' and then 'OK'.

    2. The Smartcard service is not logged on as a 'Local Service'.

    • Double-click the Smartcard service.

    • Select the second tab, 'Log On'.

    • Select 'This account'.

    • Click 'Browse'.

    • In the white text box, type: loc.

    • Then click 'Check names'.

    • The name 'Local service' now appears in the text box.

    • Then click 'OK'.

    • Leave the password boxes empty.

    • Click 'Apply'.

    • Click 'OK'.

    • Go back to the first tab, 'General', and restart the service.

    • Click 'Start'.

    • Click 'Stop'.

    In some cases there is a possibility that the system is not able to retrieve the domain information, in this case the T1C is not usable. To solve this problem you can follow these steps described here; https://www.hostinger.com/tutorials/fix-dns_probe_finished_nxdomain

    When installing the T1C the possibility of the errors 2502 or 2503 originate from the fact that permissions in the temp folder (C:\Windows\Temp) are not correct, and since the MSI installer relies on this they need to be correct. You need to have permissions next to the administrator rights.

    You need to have permissions as <My User> next to the administrator rights.

    More information can be found here; https://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/windows-8-install-some-software-using-msi/48881523-1a5d-4c43-abc4-01b1ce3ebf3a

    The Trust1Connector and some installation files are digitally signed. On some machines however the Trust1Connector is flagged/blocked by an antivirus. Disabling the antivirus temporary can allow the user to install the Trust1Connector for some antivirus tools. Below we provide procedures for some antivirus softwares to be able to install the Trust1Connector.

    If the user receives an notification that a script from the Trust1Connector is blocked as shown below:

    The procedure at https://support.eset.com/kb2908/?locale=en_US&viewlocale=en_US can be used to solved the issue.

    When using the Kaspersky and kaspersky web protection you can add an exclusion rule to the belfiusweb page. After you added this rule, restart the computer to make sure all settings are applied.

    If the connector is not starting with the error message: "Can not contact the DS service"

    Go to the user folder in %LocalAppData%

    Go to connector folder and remove the selected files below:

    Restart your pc or mac, and the restart will re-initialise the device keys.

    The problem should be solved after executing this step.

    core.readersExcludeByName("Bit4id", callback);
    {
      "data": [
      ],
      "success": true
    }

    Skip windows hello business reader

    This exclude readers will search for the term in the reader names and exclude those that match with the term

    After installation nothing happens?

    Missing VCRuntime

    Starting from v3.8.8 the VCRuntime is statically linked and will not require additional installation from the user.

    Check if VCRuntime is installed

    VCRuntime error
    C:\Windows\SysWOW64\vcruntime140.dll
    Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X64

    DNS Rebind issue (depends on the router/modem)

    Error while retrieving readers

    Is the smartcard service running?

    DNS probe finished nxdomain error

    Error during installation MSI error 2502 or 2503

    Antivirus

    ESET

    Kaspersky

    A9. T1C List Type Conent Issue

    Enable Debug Logging

    Instructions on how to enable 'debug' logging on a production device

    Introduction

    By default, the connector has tracing set to 'info', which limits logging output to it's bare minimum.

    For unexpected issues in production, the debug flags have been compiled in the connector, but they are not activeated by default.

    This page describes how to enable debug logs for OSX and Windows.

    Mac OSX

    The debug level can be modified throught the launchagent on OSX.

    The possible values are: info|warn|debug

    Update log level

    Go to the directory of the launch-agents:

    cd ~/Library/LaunchAgents/

    A connector .plist file can be found (depending on the partner, the naming is different):

    Default Trust1Connector launch-agent:

    com.t1t.t1c.api.plist

    The file has a parameter declaring the log level:

    The following line can be modified for example to 'debug' log level:

    for example:

    update to 'debug' level

    After modifying the launch-agent, the service must be restarted. To do so, you need to use launchctl:

    Stop the service:

    launchctl unload com.t1t.t1c.api.plist

    Start the service:

    launchctl load com.t1t.t1c.api.plist

    The activity monitor can be used to verify if the processes are started correctly:

    Go to the logs-folder where the connector is installed (depends on the partner configuration), by default:

    cd ~/Library/Application\ Support/Trust1Team/Trust1Connector/logs

    Open the log file and notice the debug logging appears :-).

    The connector, upon installation, creates a Windows registry entry to start when a device reboots/restarts. The entry declaration can be found when using the 'registry editor' on Windows with the following path:

    [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]

    What happens is that the t1c-launch executable is called to bootstrap/initialize the connector processes. After a succesfull bootstrap, the t1c-launch process is killed, and the following 3 processes are running:

    On Windows, the process to enable a different log level is easier than with Mac OSX.

    You just need to call the t1c-launch process with additional command line parameters.

    To find the t1c-launch binary, you typically can find it in the 'LocalAppData' folder of the logged-in user:

    In Windows Explorer type the following path:

    %localappdata%

    Select the folder from the partner who's connector has been installed:

    Open a terminal command, you can do this by starting a n ew command terminal form the Menu Search, or by typing: 'cmd' as a path in the Windows Explorer (opens a terminal window directly in the present folder).

    Execute the launcher with new parameters:

    t1c-launch --restart --log "none,t1c_rust_api=debug"

    Go to the logs-folder where the connector is installed (depends on the partner configuration), by default:

    %localappdata%/Trust1Connector/Logs

    Open the log file and notice the debug logging appears :-).

    Mac OSX Sonoma and higher Smart-card reader issue

    Smart Card Reader Issues Tracker for Sonoma

    Smart-card issue

    Quick fix

    A short fix for Mac Sonoma, more details below in the section 'Overview'.

    Execute the following steps:

    1. Open a Mac Terminal

      1. Press Command+Spacebar on your keyboard. Enter Terminal in the search field and press enter.

    2. Execute command: sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool yes

      1. copy/paste the section in bold in the terminal and press enter

    3. Unplug smart card reader from USB port

    4. Restart Mac

    5. Plug smart card reader back in USB port

    The fix has been applied and you should be able to sign a document or authenticate

    Starting from OSX Sonoma, smart card readers for Mac can fail for the following use cases:

    • detect card reader

    • execute transaction (digital signature or authentication)

    The general end-user experience is that the smart card communication fails (card reader disseappears or the transaction fails).

    A very great shout-out to Ludovic Rousseau who initially did a follow-up on impact of smart card readers in Sonoma:

    The initial solution prior to 11/2023 was very elaborate, but was made easy by applying a single command in a MAC OSX terminal:

    The command switches the MAC OSX implementation of the CCID drivers to the legacy version (the version working prior to Sonoma).

    As MAC OSX defaults using a custom CCID implementation, which still have some issues, switching to the old version is a temporary stolution.

    Form a specific moment (not at the time of writing), switching back to the default CCID implementation can be done using the following commands (in a terminal):

    Check if the built-in Apple CCID driver is active

    If the former command results in:

    This means that the built-in Apple driver is active.

    The result is 1 so the "external" (non-Apple) CCID driver is enabled.

    Returning back to default, execute:

    net stop winnat // stop
    net start winnat // start
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    	<key>Label</key>
    	<string>com.t1t.t1c.acc.api</string>
    	<key>Program</key>
    	<string>/Users/michallispashidis/Library/Application Support/Trust1Team/Trust1Connector-Acceptance/t1c-acc-api</string>
    	<key>ProgramArguments</key>
    	<array>
    		<string>/Users/michallispashidis/Library/Application Support/Trust1Team/Trust1Connector-Acceptance</string>
    		<string>-f</string>
    		...
    		<string>-x</string>
    		<string>51883</string>
    		<string>--log</string>
    		<string>none,t1c_rust_api=info</string>
    		<string>--env</string>
    		<string>prod</string>
    	</array>
    	<key>RunAtLoad</key>
    	<true/>
    </dict>
    </plist>
    
    <string>none,t1c_rust_api=info</string>
    <string>none,t1c_rust_api=debug</string>

    Restart the Connector service

    Verify logging output

    Windows

    In some cases, the t1c-reg.exe will not be running. When that's the case, the connector installed on the device is running in standalone mode. Standalone mode is the mode used when the device is NEVER part of a shared environment (VDI, Citrix, Remote desktop, ...). By default, the connector is installed with a registry process running along the api and sandbox process.

    Update log level and restart

    Verify logging output

    sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool yes
    defaults read /Library/Preferences/com.apple.security.smartcard.plist useIFDCCID
    he domain/default pair of (/Library/Preferences/com.apple.security.smartcard.plist, useIFDCCID) does not exist
    sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool no

    Overview

    Reported Bug to Mac OSX:

    OSX Forum

    Solution

    What does the command execute/change?

    How to roll-back to MAC OSX CCID implementation?

    After executing a driver switch, we have noticed that a restart is mandatory!

    You need to unplug your smart card reader from the USB port, and plug it back in after restarting

    https://www.npmjs.com/package/t1c-sdk-jswww.npmjs.com
    GitBookapp.gitbook.com
    Developer Supportdeveloper-docs.wacom.com
    Wacom STU drivers
    Signature Scope | Wacom Developer Documentationdeveloper-docs.wacom.com
    Wacom Signature Scope tool
    Logo
    Logo
    Security Verificationforums.developer.apple.com
    Security Verificationforums.developer.apple.com
    Logo
    Logo
    macOS Sonoma and smart cards statusLudovic Rousseau's blog
    macOS Sonoma and smart cards statusLudovic Rousseau's blog
    Logo
    Logo
    macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTEDLudovic Rousseau's blog
    macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTEDLudovic Rousseau's blog
    Logo
    Logo
    Latest Supported Visual C++ Redistributable DownloadsMicrosoftLearn
    Logo
    here
    Logo