Only this pageAll pages
Powered by GitBook
1 of 45

v3.5.x

Loading...

Loading...

Loading...

Loading...

Loading...

Core

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...

Payment

Loading...

Loading...

Loading...

FIle

Loading...

HSM

Loading...

Other

Loading...

Miscellaneous

Loading...

Loading...

Changelog

Release notes - Trust1Connector - Version T1C-sdk-js-3.5.5

Story

  • As an integrator I want to retrieve a consent value from the Javascript SDK

  • As a Integrator I would like to use a central registry hosted on the DS

Release notes - Trust1Connector - Version T1C-sdk-js-3.5.4

Bug

  • Trust1Connector JavaScript SDK removes the consent when the validate returns a response where an extra consent is required.

Story

  • Trust1Connector should be able to provide organization context when not requiring application tokens

Release notes - Trust1Connector - Version T1C-JS-v3.5.3

Story

  • Support Citrix multi-host session management for consent flow

Release notes - Trust1Connector - Version T1C-JS-v3.5.1

Bug

  • Issue with pinEncryption when version is not found, stops the flow

  • JS SDK for T1C v3.5 attempts to reset bulk PIN by POST request instead of GET

Release notes - Trust1Connector - Version T1C-JS-v3.5.0

Bug

  • File exchange relative path for download does not handle all cases

  • Download does not correctly build the relative path

Story

  • As an Integrator I want to provide a timeout for the dialogs

  • Migrate to Rust Jcop

  • Safenet rustification

  • eHerkenning rustification

  • Implement new architecture for shared environment, multi session host, single installation, ...

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC7

Story

  • Remote registry implementation

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC6

Bug

  • File exchange relative path for download does not handle all cases

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC5

Story

  • As an Integrator I want to provide a timeout for the dialogs

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC4

Bug

  • Download does not correctly build the relative path

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC3

Bug

  • Javascript semver check doesn't handle beta and RC versions

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC2

Story

  • Migrate to Rust Jcop

  • Safenet rustification

  • eHerkenning rustification

Release notes - Trust1Connector - Version T1C-JS-v3.5.0-RC1

Story

  • Implement new architecture for shared environment, multi session host, single installation, ...

Release notes - Trust1Connector - Version T1C-JS-v3.4.2

Bug

  • Check correct versions for backwards compatibility

Release notes - Trust1Connector - Version T1C-JS-v3.4.1

Story

  • Pin Obfuscation not working for all modules

  • base64 encode the PIN before sending it to the API

Release notes - Trust1Connector - Version T1C-JS-v3.4.1-RC3

Story

  • Pin Obfuscation not working for all modules

Release notes - Trust1Connector - Version T1C-JS-v3.4.1-RC2

Story

  • base64 encode the PIN before sending it to the API

Release notes - Trust1Connector - Version T1C-JS-v3.4.0

Story

  • I want to enable module for Certinomis

  • Migrate certigna integration with the latest token

Release notes - Trust1Connector - Version T1C-JS-v3.3.0

Bug

  • Return interface to previous state to prevent breaking applications

Release notes - Trust1Connector - Version T1C-JS-v3.2.13

Bug

  • Pkcs11 module and os dialog return decryption error

  • Update certificate model to correctly handle multiple certificates

Release notes - Trust1Connector - Version T1C-JS-v3.2.12

Bug

  • Device-key endpoint gets called in error handler instead of successhandler

Release notes - Trust1Connector - Version T1C-JS-v3.2.11

Bug

  • File-exchange ArrayBuffer should be Blob

Release notes - Trust1Connector - Version T1C-JS-v3.2.10

Bug

  • Initialising with invalid JWT does not throw an error

Release notes - Trust1Connector - Version T1C-JS-v3.2.9

Bug

  • Entity and type response object inconsistency

  • Remoteloading split TX, RX and SW value based on APDU response

Story

  • Use Device certificate to encrypt the pin value sent in clear text

  • I want to enable the module for eHerkenning

  • I want to enable module for Print Writer

Release notes - Trust1Connector - Version T1C-JS-v3.2.8

Bug

  • Aventra, Idemia, Oberthur callback functions not being triggered

  • FileExchange typing inconsistency

Story

  • Add LuxeID to the token generic interface in JS SDK

Release notes - Trust1Connector - Version T1C-JS-v3.2.7

Bug

  • Fix imports for Pkijs

Story

  • Disbable implicit any typing

Release notes - Trust1Connector - Version T1C-JS-v3.2.6

Bug

  • Fix for bulk sign reset in JS SDK causes the reader ID not to be included in certificate retrieval

Release notes - Trust1Connector - Version T1C-JS-v3.2.5

Improvement

  • Provide separate implementation for Belgian eID with Crelan reader

Trust1Connector JS SDK

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

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 elaborate 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 directly to the section: Integration in Web Applications

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

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-Proxy 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

  • 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)

The T1C-Proxy 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.

Shared Environment Client

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-Proxy for available ports and will reserve those post, prior to initialisation and startup.

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

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

The T1C-gRPC 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-gRPC will be registered and configured by the T1C-API (and restarted when needed).

Central Back-Office

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-Proxy 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.

Security

Pin Handling

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:

Share Environment Flows

Communication Stack

You can also find the source code here

When receiving ports during post-install, an user agent device is temporary RESERVED in the Agent Registry of the T1C-Proxy. 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 .

https://github.com/Trust1Team/t1c-sdk-js/tags
consent flow
Logonpm: t1c-sdk-jsnpm
LogoGitBook

Introduction

Trust1Connector v3 Documentation

A Word of Introduction

The Trust1Connector Javascript SDK is a library that purely functions as a proxy towards the Trust1Connector API. This Library does not contain any business logic.

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.

Component Diagram

Initialize Trust1Connector

Introduction

Creating the configuration object

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.

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

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

T1CConfigOptions

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.

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"
  ) {}
}

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

Parameters

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

// ...

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 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.

// When remote DS is used set the following parameter
config.dsUrl = "https://acc-ds.t1t.io";

Authenticated client

Initializing the Trust1Connector SDK

// ...

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)
    }
});

// ...

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 signature of the getImplicitConsent function is as follows;

public getImplicitConsent(codeWord: string, durationInDays?: number, 
    callback?: (error?: T1CLibException, data?: T1CClient) => void
): Promise<T1CClient>

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

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)
})

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

Full example

// 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)
        })
    }

})

Clipboard

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.

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

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;

Retrieve JWT token

GET https://ds.t1t.io/v3/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

Headers

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,
}

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

When the Trust1Connector is configured with a Distribution Service in mind you can provide a valid JWT token in the configuration object. .

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

If you need to set up the Trust1Connector with a valid JWT token you can follow the documentation on the to 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 your token to continue to use the Trust1Connector. More information on how to retrieve,use and refresh a token can be found on the .

Initialization of the Trust1Connector in many cases requires a user consent, the exception being when no registry is configured (either local or central). More information can be found . 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 is required(when a central or local registry is present). 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 which explains it in more detail

The Consent requires a user action to . 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.

There is also a but this is not fully supported yet

adding the SDK JS files to your project
downloaded
here
Consent
Consent page
clipboard API
You can retrieve such token via the Distribution Service based on the API key you received
initialize
copy some data to its clipboard

Token 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 token models used.

Models

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) {
    }
}

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.

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 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.

Applications using the Trust1Connector

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.

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

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.

The option of working without Distribution Service is also possible. You can find all the possibilities to run the Trust1Connector here

Disk Space

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

These differences will never be greater than 5Mb

Windows

Trust1Connector installer is about 15-20Mb in size. The installed size comes to 35-45Mb.

This includes the Trust1Connector API, Registry and Sandbox.

MacOS

Trust1Connector installer is about 15-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.

API Key

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.

Operating System

Right now Trust1Connector support two operating systems;

  • MacOS 10.13 or higher

    • X86 architecture

    • M1/ARM architecture

  • Windows 8.1 or higher

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.

Windows 8.1 or higher

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

Registry keys

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

Cookies

Since 3.5.x no more cookies are used.

Browsers

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

  • IE 11 (End of Life is June 15 2022)

  • All other browsers. As recent as possible

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, ...

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

Card Inserted

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.

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

Pin-Pad Capabilities

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

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

List Card-Readers - Explained Example

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

{
  "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
}

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.

Get card readers with card inserted

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.

T1CSdk.T1CClient.initialize(config).then(client => {
    var coreService = client.core();
    core.readersCardAvailable(callback);
}, err => {
    console.error(err);
});

Response:

{
  "data": [
    {
      "card": {
        "atr": "3B9813400AA503010101AD1311",
        "description": []
      },
      "id": "57a3e2e71c48cee9",
      "name": "Bit4id miniLector",
      "pinpad": false
    }
  ],
  "success": true
}

Setting up the SDK

Include Trust1Connector JS SDK

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

<!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>

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

<script defer src="./T1CSdk.js"></script>

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.

Using Trust1Connector as a module

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

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.

Consumer resources

Consumer resources are typically used from an application perspective:

  • Get pub-key certificate

  • Get version

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

  • List card-readers (with active card)

  • Get card-reader

  • List card-readers (with active cards)

  • List card-readers (with or without active card)

Executing these functionality is explained further.

Core Functionalities

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, ...

List card readers

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

Card Inserted

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.

Pin-Pad Capabilities

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):

List Card-Readers - Explained Example

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.

Get card reader with card inserted

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:

Get the Javascript SDK version

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

Get device public key

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.

Core interface

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

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

  • FINEID S1 and S4 documentation

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

Interface

Models

Examples

Create the Aventra module

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

All certificate filters

The expected response for this call should be;

all Key references

The expected response for this call should be;

all Certificates

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

  • Issuer certificate

  • Encryption 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;

Token data

This will return information of the Aventra card.

The expected response for this call should be;

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.

Root certificate

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

Authentication certificate

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.

Non repudiation certificate

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.

Issuer certificate

Encryption certificate

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

Verify pin

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

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.

The expected response for this call should be;

Bulk PIN Reset

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

Response will look like:

Authenticate

The expected response for this call should be;

Reset pin

The expected response for this call should be;

Retrieve supported algorithms

The expected response for this call should be;

Authenticated Client page
Authenticated Client page

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

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

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

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

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.

All model information can be found in the

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.

Core Service
Trust1Connector JavaScript SDK
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
}
{
  "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>;
  readersCardsUnavailable(callback?: (error: T1CLibException, data: CardReadersResponse) => void): Promise<CardReadersResponse>;
  getUrl(): string;
  getDevicePublicKey(): void;
  version(): Promise<string>;
}
export interface AbstractAventra {
    allCertFilters(): string[];
    allKeyRefs(): string[];
    allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
    tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
    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>
    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>;
    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)
});
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']
}
const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
aventra.allCerts(parseCertsBoolean, filter).then(res => {
}, err => {
    console.error(err)
})
{
    success: true,
    data: {
       authenticationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       citizenCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       nonRepudiationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       rootCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       encryptionCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
    }
}
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
    }
}
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']
    }
}

Authenticated client

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 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.

// 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);

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.

Retrieving a JWT token

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.

curl --location --request GET 'https://acc-ds.t1t.io/v3_5/tokens/application' \
--header 'apikey: your-api-key'

Example response

{
    "success": true,
    "data": "eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJ0MWNkcy1hcHAiLCJzdWIiOiJkZXZlbG9wbWVudCIsImV4cCI6MTU5OTA1MTExMywiaWF0IjoxNTk5MDQ5OTEzLCJuYmYiOjE1OTkwNDk5MDh9.LE_AdYv9PWxqSRm6-lkV_3TxInCqbf_hTwHFKCFfYwkuzex6AMkeW6FaVCOxu-EBU158S2g70i4VBpeT2TAr0IoOyjK-nalvVG5aB9MwidZMtiPlidcUfsDhsyhbhwqlhI2dzB5J5KsBmvZwpoG-Pg2koUSidruixg3SxRrCMotBRlRNKItnYgfs6_wvd_OOLXs2OlufYOD876MWcJymBK48wf9ESQ50clR3zwPAQsNnXFq2Augk0gOlCgWO1--WgaFeMnBF28b7genZXIkwZCfT82nRYtiOs0zLK2WtyireTHDgjIZif4nX8pggE7t_63Hbv8wCvv8_Mg2PfdhCMQ"
}

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

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 104026 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:

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 => {});

The function's interface is as follows;

updateJWT(jwt: string, callback?: (error: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>

This function returns an updated client which you can continue to use for your desired use-cases.

core.updateJWT("jwt").then(client => {}, error => {});

Distribution services

Environment

DS url

Acceptance

https://acc-ds.t1t.io

Production

https://ds.t1t.io

initialized correctly
initialized the Trust1Connector
Token typings model page
Supported Algorithms
Bulk PIN Reset
retrieve a valid token
refresh
API key must be exchanged

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>;
  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: TokenDataResponse) => void): Promise<TokenDataResponse>;
  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>;
  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>;
}

Models

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:

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

This function call returns:

{
  "data": [
    {
      "card": {
        "atr": "3B9813400AA503010101AD1311",
        "description": ["Belgian eID Card"]
      },
      "id": "57a3e2e71c48cee9",
      "name": "Bit4id miniLector",
      "pinpad": false
    }
  ],
  "success": true
}

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:

var beid = client.beid(reader_id);

All methods for beid will use the selected reader - identified by the reader_id.

Cardholder Information

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).

Biometric data

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

client.beid(reader_id).biometric(callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
 "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"
}

Address

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

client.beid(reader_id).address(callback);

Response:

{
 "municipality": "Hoeselt",
 "rawData": "ARJLZXJrc...AAAAAA==",
 "signature": "mhPyeRg25H...w==",
 "streetAndNumber": "Kerkstraat X",
 "version": "0",
 "zipcode": "3730"
}

Picture

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

client.beid(reader_id).picture(callback);

Response:

{
  "data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
  "success": true
}

Token info

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

{
  "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
}

Certificates

Exposes all the certificates publicly available on the smart card.

Root Certificate

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:

client.beid(reader_id).rootCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Authentication Certificate

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:

client.beid(reader_id).authenticationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Intermediate Certificate (citizen)

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:

client.beid(reader_id).intermediateCertificates(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

client.beid(reader_id).nonRepudiationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Encryption Certificate (RRN)

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:

client.beid(reader_id).encryptionCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Data Filter

Filter Card Holder Data

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

Options are; biometric, picture and address

var filter = [];
client.beid(reader_id).allData({ filters: filter}, callback);

Response:

{
 "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"
 }
}

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

var filter = ['biometric'];
client.beid().allData({ filters: filter }, callback);

Response:

{
 "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"
 }
}

Filter Certificates

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

var filter = [];
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 },
 "intermediateCertificates": {
  ...
 },
 "encryptionCertificate": {
  ...
 }
}

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

var filter = ['rootCertificate'];
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 }
}

Sign Data

Algorithm

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

  • sha512

For beid 1.8 we have;

  • sha2_256

  • sha2_384

  • sha2_512

  • sha3_256

  • sha3_384

  • sha3_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;

Belgian EID 1.7

Provided algorithm value

Selected algorithm by T1C

md5

md5

sha1

sha1

sha256

sha256

sha512

sha512

any other value

sha256

Belgian EID 1.8

Provided algorithm value

Selected algorithm by T1C

sha2_256

sha2_256

sha2_384

sha2_384

sha2_512

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

Signing

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:

var filter = null;
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 },
 "intermediateCertificates": {
  ...
 },
 "encryptionCertificate": {
  ...
 }
}

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'.

Signing with a Crelan card reader

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.

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true,
      "txId": "1234",
      "language": "fr"
}
client.beid(reader_id).sign(data, callback);

Crelan card readers only support nl, fr, and de as languages

Sign Hash without 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:

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true
}
client.beid(reader_id).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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

var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": false
}
client.beid(reader_id).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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.

const data = {
    algorithm: "sha256",
    data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
    pin: "1234"
}
const bulk = true;
beid.sign(data, bulk).then(res => {
}, err => {
    console.error(err)
})

Bulk PIN Reset

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

beid.resetBulkPin().then(res => {
}, err => {
    console.error(err)
})

Response will look like:

{
    "success": true,
    "data": true
}

Calculate Hash

In order to calculate a hash from the data to sign, you need to know the algorithm you will use in order to sign.

This is sample text to demonstrate siging with Belgian eID

Hexadecimal result:

135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b

Base64-encoded result:

E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=

Now we can sign the data:

var data = {
      "pin":"...",
      "algorithm":"sha256",
      "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
}
client.beid(reader_id).signData(data, callback);

Result:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

Note: If you want to convert a binary signed hash to HEX (for development) you can use for example an online hexdump tool:

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
client.beid(reader_id).verifyPin(data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
client.beid(reader_id).verifyPin(data, callback);

Response:

{
  "verified": true
}

Verify PIN - retries left

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:

  $("#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);
  });

Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status.

Authentication

Algorithm

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

  • sha512

For beid 1.8 we have;

  • sha2_256

  • sha2_384

  • sha2_512

  • sha3_256

  • sha3_384

  • sha3_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;

Belgian EID 1.7

Provided algorithm value

Selected algorithm by T1C

md5

md5

sha1

sha1

sha256

sha256

sha512

sha512

any other value

sha256

Belgian EID 1.8

Provided algorithm value

Selected algorithm by T1C

sha2_256

sha2_256

sha2_384

sha2_384

sha2_512

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

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.beid(reader_id).authenticate(data, callback);

    Response:

    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }

    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 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.

Get valid algorithms to use for Sign or Authenticate

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

generic.allAlgoRefs(module, callback);

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

{
    "success": true,
    "data": ["sha1", "sha256"]
}

Generic token

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 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.

Interface

export interface AbstractEidGeneric {
  getModuleDescription(module: string, callback?: (error: T1CLibException, data: DataObjectResponse) => void): Promise<DataObjectResponse>;
  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: TokenDataResponse) => void): Promise<TokenDataResponse>;
  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>;
  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>;
}

Models

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": [
    {
      "card": {
        "atr": "3B9813400AA503010101AD1311",
        "description": ["Belgian eID Card"]
      },
      "id": "57a3e2e71c48cee9",
      "name": "Bit4id miniLector",
      "pinpad": false,
      "suggestedModule": "beid"
    }
  ],
  "success": true
}

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.

Using the generic interface can be done as follows;

var generic = client.generic(selected_reader.id, pin, pinType);

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

Cardholder Information

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).

Biometric data

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

generic.biometric(module, options, callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
 "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"
}

Address

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

generic.address(module, callback);

Response:

{
 "municipality": "Hoeselt",
 "rawData": "ARJLZXJrc...AAAAAA==",
 "signature": "mhPyeRg25H...w==",
 "streetAndNumber": "Kerkstraat X",
 "version": "0",
 "zipcode": "3730"
}

Picture

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

generic.picture(module, callback);

Response:

{
  "data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
  "success": true
}

Token info

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

{
  "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
}

Certificates

Exposes all the certificates publicly available on the smart card.

Root Certificate

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:

generic.rootCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Authentication Certificate

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:

generic.authenticationCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Intermediate Certificate (citizen)

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:

generic.intermediateCertificates(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Encryption Certificate (RRN)

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:

generic.encryptionCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Data Filter

Filter Card Holder Data

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

var filter = [];
generic.allData(module, { filters: filter}, callback);

Response:

{
 "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"
 }
}

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

var filter = ['biometric'];
generic.allData(module, { filters: filter }, callback);

Response:

{
 "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"
 }
}

Filter Certificates

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

var filter = [];
generic.allCerts(module, parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
 ...
 },
 "authenticationCertificate": {
 ...
 },
 "nonRepudiationCertificate": {
 ...
 },
 "intermediateCertificates": {
 ...
 },
 "encryptionCertificate": {
 ...
 }
}

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

var filter = ['rootCertificate'];
generic.allCerts(module, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 }
}

Sign Data

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:

var filter = null;
generic.allCerts(module, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
 ...
 },
 "authenticationCertificate": {
 ...
 },
 "nonRepudiationCertificate": {
 ...
 },
 "intermediateCertificates": {
 ...
 },
 "encryptionCertificate": {
 ...
 }
}

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'.

Sign Hash without 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:

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true
}
generic.sign(module, data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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

var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": false
}
generic.sign(module, data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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.

const data = {
    algorithm: "sha256",
    data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
    pin: "1234"
}
const bulk = true;
generic.sign(module, data, bulk).then(res => {
}, err => {
    console.error(err)
})

Bulk PIN Reset

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

generic.resetBulkPin(module).then(res => {
}, err => {
    console.error(err)
})

Response will look like:

{
    "success": true,
    "data": true
}

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
generic.verifyPin(module, data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
generic.verifyPin(module, data, callback);

Response:

{
  "verified": true
}

Authentication

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:

var data = {
  "pin": "...",
  "algorithm": "sha1",
  "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
generic.authenticate(module, data, callback);

Response:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

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

Get valid algorithms to use for Sign or Authenticate

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

generic.allAlgoRefs(module, callback);

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

{
    "success": true,
    "data": ["sha1", "sha256"]

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/downloads/installer endpoint of the Distribution Service (e.g. https://acc-ds.t1t.io/v3/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/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/downloads/installers/{{OS}}/versions/{{version}}: This endpoint allows you to download a specific version of a T1C installer for a specific OS.

The automatic user-agent detection does not differentiate between ARM/M1 and Intel Mac devices

Differentiate between MacOS architectures

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);

# Intel x86_64
https://ds.t1t.io/v3/downloads/installers/macos

# ARM64
https://ds.t1t.io/v3/downloads/installers/macosarm

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

Distribution services

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.

Environment

DS url

Acceptance

https://acc-ds.t1t.io

Production

https://ds.t1t.io

Status codes / error handeling

Introduction

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.

Status Codes

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:

Error format

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;

The following 2 digits describe the type of error;

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.

Codes to expect

The following list are codes that you can 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

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

Diplad (BeLawyer)

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

“De advocaat moet voor zijn identificatie en voor de authenticatie beschikken over de elektronische CCBE-advocatenkaart.”

Interface

Module

Models

Examples

Initializing Diplad Module

All Data

Response will look like:

Biometric Data

Response will look like:

Picture

Response will look like:

All Certificates

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 filter is optional

Response will look like:

Root 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.

Response will look like:

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.

Response will look like:

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.

Response will look like:

Verify PIN

  • 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:

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.

Response will look like:

Authenticate

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.

Response will look like:

Get Supported Algorithms

Response will look like:

Bulk PIN Reset

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

Response will look like:

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.

Configuration

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;

Some of the config options of the v3 are still in review and can be removed up until the final release of the v3, in the table below you will find more information

Initialisation

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;

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

Models

Examples

Create the Idemia module

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

All certificate filters

The expected response for this call should be;

all Key references

The expected response for this call should be;

all Certificates

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;

Token data

This will return information of the Aventra card.

The expected response for this call should be;

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.

Root certificate

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

Authentication certificate

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:

Non repudiation certificate

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:

Issuer certificate

Encryption certificate

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

Verify pin

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

Sign

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

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.

The expected response for this call should be;

Bulk PIN Reset

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

Response will look like:

Authenticate

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;

Retrieve supported algorithms

The expected response for this call should be;

Chambersign

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 Chambersign token is a token that requires for the middleware of Chambersign to be installed prior to using it on the Trust1Connector.

The middleware of Chambersign has to be installed to be able to fully use the Chambersign

Detect if Middleware has been installed.

Windows

The chambersign software for windows requires administration rights to be installed. After installation the location will be:

x64 & x86 ; C:\Program Files\ChamberSign

To check if this has been installed we can use the File-exchange create type function and then check the contents of the (sub)-folders.

To check if the middleware is installed the sample code below is a good start to use the File-Exchange to check if the middleware has been installed and its safe to continue to use the ChamberSign middleware and the Trust1Connector.

Interface

Be aware that for chambersign only the following functions are supported at this time:

  • authenticate

  • sign

  • verifyPin

  • AuthenticationCertificate

  • NonRepudiationCertificate

  • AllCerts(auth, nonrep)

  • allAlgoRefs

  • resetBulkPin

Models

Initialise the Trust1Connector JS

Initialise a Trust1Connector client with a valid configuration:

Obtain the Reader information

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 chambersign integration.

Certificates

Exposes all the certificates publicly available on the smart card.

Authentication Certificate

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:

Non-repudiation Certificate

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:

Filter Certificates

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:

Sign Data

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'.

Sign Hash without 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 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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

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

Response will look like:

Verify PIN

Verify PIN without pin-pad

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:

Verify PIN with pin-pad

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

Response:

Authentication

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.

Get valid algorithms to use for Sign or Authenticate

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)

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

Models

Examples

Create the Oberthur module

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

All certificate filters

The expected response for this call should be;

all Key references

The expected response for this call should be;

all Certificates

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

  • Issuer certificate

  • Encryption 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;

Token data

This will return information of the Aventra card.

The expected response for this call should be;

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.

Root certificate

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

Authentication certificate.

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:

Non repudiation certificate

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:

Issuer certificate

Encryption certificate

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

Verify pin

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

Sign

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

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.

The expected response for this call should be;

Bulk PIN Reset

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

Response will look like:

Authenticate

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;

Retrieve supported algorithms

The expected response for this call should be;

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

Models

Initialise the Trust1Connector JS

Initialise a Trust1Connector client with a valid configuration:

Obtain the Reader information

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.

Certificates

Exposes all the certificates publicly available on the smart card.

Authentication Certificate

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:

Non-repudiation Certificate

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:

Encryption Certificate

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:

Root Certificate/Issuer Certificate

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

Response:

Filter Certificates

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:

Sign Data

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'.

Sign Hash without 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 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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

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

Response will look like:

Verify PIN

Verify PIN without pin-pad

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:

Verify PIN with pin-pad

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

Response:

Authentication

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.

Get valid algorithms to use for Sign or Authenticate

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)

All model information can be found in the

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.

You can use the following online tool to calculate the SHA256:

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:

For more information about the error codes you can check the

All model information can be found in the

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.

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 :

More info at .

All model information can be found in the

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 PIN can provided/entered in the same way as

The PIN can provided/entered in the same way as

For more information regarding initialization we suggest the

All model information can be found in the

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 version of the middleware supported is; Mac: Windows:

This is an example of how this could be integrated. You are free to implement this however you like. Information for the file-exchange module can be found

All model information can be found in the

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.

All model information can be found in the

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.

All model information can be found in the

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.

calculate SHA256
hex to base64 converter
http://www.fileformat.info/tool/hexdump.htm
Error codes page
Token typings model page
Token typings model page
Bulk Sign Reset
Bulk Sign Reset
{
  description: "some error description",
  code: "some error code"
}

Error

Origin

1XXXXX

General

2XXXXX

Transaction service

3XXXXX

Certificate service

4XXXXX

Meta service

5XXXXX

File exchange

6XXXXX

Identity service

7XXXXX

Reader service

8XXXXX

Proxy

Error

Type

X01XXX

Reader

X02XXX

Card

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

Code

Exception type

10000

GeneralConnectorException

XXX000

InvalidDigestException

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

XXX996

ClientErrorException (invalid input body or request was send)

XXX997

SandboxRuntimeException (failure in the sanbox, API will implicitly restart the sandbox)

Error code

Description

111003

Module not implemented

106029

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error code

Description

312998

Module not implemented

611004

Parameter error

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

Error

Description

312998

Module not implemented

611004

Parameter error

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

Error

Description

312998

Module not implemented

611004

Parameter error

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

Error

Description

505126

Configuration error / none is found

504123

Access exception/ not enough access rights - General error

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

Old code

New code

example description

351

504128

/Library/Updates/ProductMetadata2.plist (Operation not permitted)

352

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…)

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: TokenDataResponse) => void): Promise<TokenDataResponse>;
  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>;
  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 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"
  ) {}
}
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);
});
export interface AbstractIdemia {
    allCertFilters(): string[];
    allKeyRefs(): string[];
    allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
    tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
    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>
    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 idemia = res.client.idemia(readerId);
}, err => {
    console.error(error)
});
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 => {
}, err => {
    console.error(err)
})
{
    success: true,
    data: {
       authenticationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       citizenCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       nonRepudiationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       rootCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       encryptionCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
    }
}
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
    }
}
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 entity = "chambersign";
const type = "middleware";
const initPath = "C:\\Program Files\\ChamberSign"

T1CSdk.T1CClient.initialize(config).then(res => {
    client = res;
    core = client.core();
    let fileex = client.fileex();

    const middlewareInstalled = await isMiddlewareInstalled(fileex);
    if (middlewareInstalled) {
        // Middleware is installed you can use the chambersign token with the T1C
    } else {
        // Middleware not installed please install before using it with the T1C
    }
    
}, err => {
    errrorHandler(err);
});


async function isMiddlewareInstalled(fileexClient) {
    fileexClient.existsType(entity, type).then(existsRes => {
        if (existsRes.data) {
            // Type exists
            return checkFilesPresent(fileexClient);
        } else {
            // Type does not exist        
            fileexClient.createType(entity, type, initPath).then(createRes => {
                return checkFilesPresent(fileexClient);
            }, err => {
                errrorHandler(err);
            })
        }
    }, err => {
        // Type exists error, try to create and then check if middleware is installed
        fileexClient.createType(entity, type, initPath).then(createRes => {
            return checkFilesPresent(fileexClient);
        }, err => {
            errrorHandler(err);
        })
    });
}


async function checkFilesPresent(fileexClient) {
    await fileexClient.existsFile(entity, type, "HashLogic\\bin\\idoPKCS.dll").then(existsFileRes => {
        return existsFileRes;
    }, err => {
        return false;
    })
}
export interface AbstractEidGeneric {
//  getModuleDescription(module: string, callback?: (error: T1CLibException, data: DataObjectResponse) => void): Promise<DataObjectResponse>;
//  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: TokenDataResponse) => void): Promise<TokenDataResponse>;
//  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>;
  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>;
}
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 module = "chambersign";
var generic = client.generic(selected_reader.id);
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>
    }    
}
var filter = [];
generic.allCerts(module, parseCerts, { filters: filter}, callback);
{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}
var filter = ['authenticationCertificate'];
generic.allCerts(module, { filters: filter}, callback);
{
 "authenticationCertificate": {
  ...
 }
}
var filter = null;
generic.allCerts(module, { filters: filter}, callback);
{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}
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...="
  }
}
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"]
}
export interface AbstractOberthur73 {
    allCertFilters(): string[];
    allKeyRefs(): string[];
    allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
    tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
    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>
    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 oberthur = res.client.oberthur(readerId);
}, err => {
    console.error(error)
});
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 => {
}, err => {
    console.error(err)
})
{
    success: true,
    data: {
       authenticationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       citizenCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
       nonRepudiationCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       rootCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },,
       encryptionCertificate?: {
            certificate?: TokenCertificateObject,
            certificates?: Array<TokenCertificateObject>
       },
    }
}
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
    }
}
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']
    }
}
export interface AbstractEidGeneric {
//  getModuleDescription(module: string, callback?: (error: T1CLibException, data: DataObjectResponse) => void): Promise<DataObjectResponse>;
//  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: TokenDataResponse) => void): Promise<TokenDataResponse>;
//  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>;
  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>;
}
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 module = "airbus";
var generic = client.generic(selected_reader.id);
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;
generic.allCerts(module, { filters: filter}, callback);
{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}
var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true,
      "id": "id.."
}
generic.sign(module, data, callback);
{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}
var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": false,
      "id": "id.."
}
generic.sign(module, data, callback);
{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}
const data = {
    algorithm: "sha256",
    data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
    pin: "1234",
    id: "id.."
}
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=",
  "id": "id.."
}
generic.authenticate(module, data, callback);
{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}
generic.verifyPin(module, data, callback);
generic.allAlgoRefs(module, callback);
{
    "success": true,
    "data": ["sha1", "sha256"]
}

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

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) {}
}

EMV

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 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

Get EMV container object

Initialise a Trust1Connector:

T1CSdk.initialize(config).then(res => {

}, err => {
    console.error(error)
});

Get the EMV service:

var emv = client.emv(reader_id);

Call a function for the EMV container:

function callback(err,data) {
    if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
    else {console.log(JSON.stringify(data, null, '  '));}
}
emv.readData(callback)

Obtain the Reader-ID

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. 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:

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

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:

var emv = client.emv(reader_id);

All methods for emv will use the selected reader - identified by the reader_id.

Reading data

Applications

List the supported applications on the EMV card

client.emv(reader_id).readData(callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
  "data": [
      {
        "aid": "A0000000048002", 
        "name": "MAESTRO", 
        "priority": 1
      },{
        "aid": "A0000000048008", 
        "name": "MASTERCARD",
        "priority": 1
      }
    ],
  "success": true
}

Application data

The application data contains information of the holder of the card, the validity, the primary account number, ...

client.emv(reader_id).readApplicationData(callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
 "country": "BE",
 "countryCode": "0056",
 "effectiveDate": "190201",
 "expirationDate": "241231",
 "language": "nlen",
 "name": "",
 "pan": "670...001"
}

Issuer Public Key Certificate

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.

// Application ID can be retrieved with the Applications endpoint
var aid = "..."

client.emv(reader_id).issuerPublicCertificate(aid, callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
  "data": {
    "data": "base64 encoded data", 
    "exponent": "base64 encoded data", 
    "remainder": "base64 encoded data"
  }, 
  "success": true
}

ICC Public Key Certificate

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.

// Application ID can be retrieved with the Applications endpoint
var aid = "..."

client.emv(reader_id).iccPublicCertificate(aid, callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
 "certificate": "dxL8JnkxHneX36tdQCzz...HC3Wpt/qppk008q9OMDgVp0F7NJjCC2mXg3b/qD7c09WFXUwZ+XdkmIefhoZT/kme4QEoD49+ppQiqSeCaRjn6N0OetcjleWkPej8vE0QG4mLlG/edWTVbfMGbED9Kbjf4ooauNnq+iAVwgHedsDpdDWJLhV8sDSLQgZ1B3fMQuyZIaD79+X+H9fbhmJg+j7Lr638srglWM9VlthaWjRbFH2HzNEiQ9sOE20lmj6WM6zdYas9+Z4hcwZqWbeiTeIJDwDc6w==",
 "exponent": "AQAB",
 "remainder": ""
}

Verify PIN

Verify PIN without pin-pad

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

var data = {
    "pin": "...."
}
client.emv().verifyPin(data, callback);

Response:

{
 "verified": true
}

Verify PIN with pin-pad

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

var data = {}
client.emv().verifyPin(data, callback);

Response:

{
 "verified": true
}

Verify PIN - retries left

After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

  $("#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);
  });

The following error message will be returned when PIN is wrong:

{
  "code": 301,
  "description": "Wrong pin, 2 tries remaining",
  "success": false
}

After a second wrong PIN verification:

{
  "code": 301,
  "description": "Wrong pin, 1 try remaining",
  "success": false
}

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

301

Error: the PIN is blocked

Error Handling

Error Object

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:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

The error object returned:

{
  success: false,
  description: "some error description",
  code: "some error code"
}

For the error codes and description, see Status codes.

Codex Deontologie voor Advocaten
https://www.diplad.be/en-GB/t/23/elektronische-advocatenkaart.aspx
Initialize page
6.17.1
6.12.0
here
Token typings model page
Token typings model page
Token typings model page
Token typings model page
Token typings model page
Supported Algorithms
Bulk PIN Reset
Verify PIN
Verify PIN
Supported Algorithms
Bulk PIN Reset
Bulk Sign Reset
Bulk Sign Reset
Supported Algorithms
Bulk PIN Reset

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)

t1cApiPort

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

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

/

Jcop3

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 Jcop3 module exposed on the Trust1Connector onto your web application.

Interface

export interface AbstractEidGeneric {
  allCerts(module: string, parseCerts?: boolean,  filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
  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>;
  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>;
}

Models

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 module = "jcop3";
var generic = 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.

Certificates

Exposes all the certificates publicly available on the smart card.

Authentication Certificate

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:

generic.authenticationCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Encryption Certificate

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:

generic.encryptionCertificate(module, parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Filter Certificates

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

var filter = [];
generic.allCerts(module, parseCerts, { filters: filter}, callback);

Response:

{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
 ...
 },
 "encryptionCertificate": {
 ...
 }
}

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

var filter = ['authenticationCertificate'];
generic.allCerts(module, { filters: filter}, callback);

Response:

{
 "authenticationCertificate": {
  ...
 }
}

Sign Data

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:

var filter = null;
generic.allCerts(module, { filters: filter}, callback);

Response:

{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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'.

Sign Hash without 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:

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true,
      "id": "id.."
}
generic.sign(module, data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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

var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": false,
      "id": "id.."
}
generic.sign(module, data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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.

const data = {
    algorithm: "sha256",
    data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
    pin: "1234",
    id: "id.."
}
const bulk = true;
generic.sign(module, data, bulk).then(res => {
}, err => {
    console.error(err)
})

Bulk PIN Reset

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

generic.resetBulkPin(module).then(res => {
}, err => {
    console.error(err)
})

Response will look like:

{
    "success": true,
    "data": true
}

Verify PIN

Verify pin only check the global sign pin at this moment

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
generic.verifyPin(module, data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
generic.verifyPin(module, data, callback);

Response:

{
  "verified": true
}

Authentication

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:

var data = {
  "pin": "...",
  "algorithm": "sha1",
  "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
  "id": "id.."
}
generic.authenticate(module, data, callback);

Response:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

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

generic.verifyPin(module, data, callback);

Get valid algorithms to use for Sign or Authenticate

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

generic.allAlgoRefs(module, callback);

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

{
    "success": true,
    "data": ["sha1", "sha256"]
}

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.

Generating a random clipboard value

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.

public static generateConsentToken(): string

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

To call this;

# regular imported javascript via script tag
T1CSdk.T1CClient.generateConsentToken()
# Import loaded via NPM
import {T1CClient} from "t1c-sdk-js";

T1CClient.generateConsentToken()

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

User clipboard remark

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.

Sending an implicit consent request can be done as follows:

T1CSdk.T1CClient.initialize(config).then(res => {
    client = res;
    console.log("Client config: ", client.localConfig)
    core = client.core();
}, err => {
    if (err.code == 814501) {
        console.log(err)
        client = err.client
        $('#consentModal').modal('show', {
            keyboard: false
        });
        $('.consent-token').text(makeid(20));
    } else if(err.code == 815500) {
        // Agent not registered --> contact support
    } else if (err.code == 112999) {
        // Unavailable
    } else {
        console.error("T1C error:", err)
    }
}); 

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

$('#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)
    })
});

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.

Eherkenning

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 Eherkenning module exposed on the Trust1Connector onto your web application.

Middleware of Eherkenning has to be installed to be able to fully use the Eherkenning token.

Luxembourg ID

Introduction

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

Interface Summary

The Abstract Lux eID interface is summarized in the following snippet:

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: TokenDataResponse) => void): Promise<TokenDataResponse>;
  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>;
  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>;
}


export class PinType {
  static PIN = 'Pin';
  static CAN = 'Can';
}

Each interface will be covered on this wiki, accompanied with example code and response objects.

Get Luxembourg ID container object

For more information on how to configure the T1C-JS client library see Client Configuration. Initialize a gclClient:

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

Get the Luxembourg ID container service:

var luxeid = client.luxeid(reader_id, pin, pinType);

Note that we pass both the reader_id, 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:

function callback(err,data) {
    if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
    else {console.log(JSON.stringify(data, null, '  '));}
}
luxeid.biometric(callback);

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.

Obtain the Reader-ID

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. 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:

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

This function call returns:

{
  "data": [
    {
      "card": {
        "atr": "3B8F800180318065B0850300EF120FFF82900073",
        "description":["Grand Duchy of Luxembourg / Identity card with LuxTrust certificate (eID)"
      },
      "id": "57a3e2e71c48cee9",
      "name": "iDentiv CL",
      "pinpad": false
    }
  ],
  "success": true
}

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:

var luxeid = client.luxeid(reader_id, pin, pinType);

All methods for luxeid will use the selected reader - identified by the reader_id.

Cardholder Information

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).

Biometric Information

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

client.luxeid(reader_id, pin, pinType).biometric(callback);

An example callback:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

Response:

{
  "data": {
    "birthDate": "830819",
    "documentNumber": "SPEC04168",
    "documentType": "ID",
    "firstName": "SPECIMEN",
    "gender": "F",
    "issuingState": "LUX",
    "lastName": "SPECIMEN",
    "nationality": "LUX",
    "validityEndDate": "251116",
    "validityStartDate": "151116"
  },
  "success": true
}

Address

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

client.luxeid(reader_id, pin, pinType).address(callback);

Response:

{
  "data": {
    //TBD
  },
  "success": true
}

Picture

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

client.luxeid(reader_id, pin, pinType).picture(callback);

Response:

{
  "data": {
    "height": 320,
    "image": "/0//UQAvAAAAAADwAAABQAAAAAAAAAAAAAAA8AAA....uq9eK159DRO61Ufrf9ICA/9k=",
    "width": 240
  },
  "success": true
}

Signature Image

Contains an image of the card holder's signature stored on the smart card. The service can be called:

client.luxeid(reader_id, pin, pinType).signatureImage(callback);

Response:

{
  "data": {
    "image": "/0//UQAvAAAAAADwAAABQAAAAAAAAAAAAAAA8AAA....uq9eK159DRO61Ufrf9ICA/9k=",
    "raw_data": "/0//UQAAAAAADwAAARLKEQDAAAAAAAAAAAAAA8AAA....dl42fgr367PCSA321/9k="
  },
  "success": true
}

Certificates

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

Certificate Chain

Root Certificate

Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'intermediate certificate'. The service can be called:

client.luxeid(reader_id, pin, pinType).rootCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

There are 2 root certificates on the card, one is the issuer certificate of the intermediate

Authentication Certificate

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:

client.luxeid(reader_id, pin, pinType).authenticationCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

client.luxeid(reader_id, pin, pinType).nonRepudiationCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Data Filter

Filter Card Holder Information

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

var filter = [];
client.luxeid(reader_id, pin, pinType).allData({ filters: filter, parseCerts: true }, callback);

Response:

{
  "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
}

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':

// 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);

Response:

{
  "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
}

Filter Certificates

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

var filter = [];
client.luxeid(reader_id, pin, pinType).allCerts({ filters: filter, parseCerts: true }, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 },
 "intermediateCertificates": {
  ...
 },
 "encryptionCertificate": {
  ...
 }
}

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':

// 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);

Response:

{
 "authenticationCertificate": {
  ...
 },
}

Sign Data

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:

var filter = ['root-certificates','authentication-certificate','non-repudiaton-certificate'];
client.luxeid(reader_id, pin, pinType).allCertificates({ filters: filter, parseCerts: false }, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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'.

Sign Hash

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

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.luxeid(reader_id, pin, pinType).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
}

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

Calculate Hash

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:

This is sample text to demonstrate siging with Luxembourg eID

Hexadecimal result:

135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b

Base64-encoded result:

E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=

Now we can sign the data:

var data = {
      "pin":"...",
      "algorithm":"sha256",
      "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
}
client.luxeid(reader_id, pin, pinType).sign(data, callback);

Result:

{
  "data": "C7SG5eix1+lzMcZXgL0bCL+rLxKhd8ngrSj6mvlgooWH7CloEU13Rj8QiQHdhHnZgAi4Q0fCMIqAc4dn9uW9OP+MRitimRpYZcaDsGrUehPi/JpOD1e+ko7xKZ67ijUU4KTmG4HXc114oJ7xxx3CGL7TNFfvuEphLbbZa+9IZSSnYDOOENJqhggqqu7paSbLJrxC2zaeMxODKb5WSexHnZH6NnLPl2OmvPTYtxiTUMrLbFRsDRAziF6/VQkgM8/xOm+1/9Expv5DSLRY8RQ+wha6/nMlJjx50JszYIj2aBQKp4AOxPVdPewVGEWF4NF9ffrPLrOA2v2d7t5M4q7yxA==",
  "success": true
}

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
gcclient.luxeid(reader_id, pin, pinType).verifyPin(data, callback);

Response:

{
  "success": true
}

Verify PIN - retries left

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:

  $("#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);
  });

Note that, when the user has at least one retry left,entering a correct PIN resets the PIN retry status.

Authentication

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="
    }
    gclClient.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 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.

Error Handling

Error Object

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:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

The error object returned:

{
  success: false,
  description: "some error description",
  code: "some error code"
}

For the error codes and description, see Status codes.

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>;
  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>;
}

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: Core Services.

For demonstration purpose we'll add a simple console output callback, which we'll use throughout the documentation.

function callback(err,data) {
    if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
    else {console.log(JSON.stringify(data, null, '  '));}

Just as an example, we instantiate a new gcl (local client) and ask for all connected smart card readers:

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

This will returns us all connected readers:

{
  "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
}

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).

Certificates

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

The root and intermediate certificates are both stored as root certificates.

Certificate Chain

Root Certificate

Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'intermediate certificate'. The service can be called:

client.luxtrust(reader_id).rootCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

There are 2 root certificates on the card, one is the issuer certificate of the intermediate

Authentication Certificate

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:

client.luxtrust(reader_id).authenticationCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Signing Certificate

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:

client.luxtrust(reader_id).signingCertificate({ parseCerts: true }, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Data Filter

Filter Certificates

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

var filter = [];
client.luxtrust(reader_id).allCerts({ filters: filter, parseCerts: true }, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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':

var filter = ['authentication-certificate'];
client.luxtrust(reader_id).allCerts({ filters: filter, parseCerts: true }, callback);

Response:

{
 "rootCertificate": {
  ...
 }
}

Sign Data

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:

var filter = ['root-certificates','authentication-certificate','signing-certificate'];
client.luxtrust(reader_id).allCertificates({ filters: filter, parseCerts: false }, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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'.

Sign Hash

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

Without a pinpad reader

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.luxtrust(reader_id).sign(data, callback);

With a pinpad reader

var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.luxtrust(reader_id).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": "W7wqvWA8m9SBALZPxN0qUCZfB1O/WLaM/silenLzSXXmeR+0nzB7hXC/Lc/fMru82m/AAqCuGTYMPKcIpQG6MtZ/SGVpZUA/71jv3D9CatmGYGZc52cpcb7cqOVT7EmhrMtwo/jyUbi/Dy5c8G05owkbgx6QxnLEuTLkfoqsW9Q="
}

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.

Calculate Hash

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:

This is sample text to demonstrate siging with LuxTrust smartcard or signing stick

Hexadecimal result:

135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95b

Base64-encoded result:

E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=

Now we can sign the data (remove the pin property for pinpad readers):

var data = {
      "pin":"...",
      "algorithm_reference":"sha256",
      "data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
}
client.luxtrust(reader_id).sign(data, callback);

Result:

{
  "data": "C7SG5eix1+lzMcZXgL0bCL+rLxKhd8ngrSj6mvlgooWH7CloEU13Rj8QiQHdhHnZgAi4Q0fCMIqAc4dn9uW9OP+MRitimRpYZcaDsGrUehPi/JpOD1e+ko7xKZ67ijUU4KTmG4HXc114oJ7xxx3CGL7TNFfvuEphLbbZa+9IZSSnYDOOENJqhggqqu7paSbLJrxC2zaeMxODKb5WSexHnZH6NnLPl2OmvPTYtxiTUMrLbFRsDRAziF6/VQkgM8/xOm+1/9Expv5DSLRY8RQ+wha6/nMlJjx50JszYIj2aBQKp4AOxPVdPewVGEWF4NF9ffrPLrOA2v2d7t5M4q7yxA==",
  "success": true
}

Verify PIN

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

Without a pinpad reader

var data = {
      "pin":"..."
}
client.luxtrust(reader_id).verifyPin(data, callback);

With a pinpad reader

var data = {}
client.luxtrust(reader_id).verifyPin(data, callback);

Response:

{
  "success": true
}

Authentication

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:

Without a pinpad reader

var data = {
  "pin": "...",
  "algorithm_reference": "sha1",
  "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.luxtrust(reader_id).authenticate(data, callback);

With a pinpad reader

var data = {
  "algorithm_reference": "sha1",
  "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.luxtrust(reader_id).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 and sha256.

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 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.

Error Handling

Error Object

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:

function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}

The error object returned:

{
  success: false,
  description: "some error description",
  code: "some error code"
}

For the error codes and description, see Status codes..

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.

Interface

export interface AbstractCertinomis {
    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>;
    allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
    resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}

Models

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;

var client = client.certinomis(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.

Certificates

Exposes all the certificates publicly available on the smart card.

Authentication Certificate

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:

client.authenticationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

client.nonRepudiationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Filter Certificates

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

var filter = [];
client.allCerts(parseCerts, { filters: filter}, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

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

var filter = ['authenticationCertificate'];
client.allCerts({ filters: filter}, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Sign Data

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

var filter = null;
client.allCerts({ filters: filter}, callback);

Response:

{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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.

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

var data = {
      "pin":"...",
      "algorithm":"sha256",
      "data":"dGVzdA=="
      "osDialog": true
}
client.sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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.

const data = {
    algorithm: "sha256",
    data: "dGVzdA==",
    pin: "1234"
}
const bulk = true;
client.sign(data, bulk).then(res => {
}, err => {
    console.error(err)
})

Bulk PIN Reset

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

client.resetBulkPin(module).then(res => {
}, err => {
    console.error(err)
})

Response will look like:

{
    "success": true,
    "data": true
}

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
client.verifyPin(data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
client.verifyPin(data, callback);

Response:

{
  "verified": true
}

Authentication

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": "sha256",
  "data":"dGVzdA=="
}
client.authenticate(data, callback);

Response:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

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

Get valid algorithms to use for Sign or Authenticate

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

client.allAlgoRefs(callback);

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

{
    "success": true,
    "data": ["sha256"]
}

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.

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>;
    allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
    resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}

Models

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;

var client = client.certigna(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.

Certificates

Exposes all the certificates publicly available on the smart card.

Authentication Certificate

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:

client.authenticationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

client.nonRepudiationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Filter Certificates

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

var filter = [];
client.allCerts(parseCerts, { filters: filter}, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

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

var filter = ['authenticationCertificate'];
client.allCerts({ filters: filter}, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Sign Data

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

var filter = null;
client.allCerts({ filters: filter}, callback);

Response:

{
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 }
}

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'.

Sign Hash without 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:

var data = {
      "pin":"...",
      "algorithm":"sha256",
      "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
      "osDialog": true
}
client.sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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

var data = {
      "algorithm": "sha256",
      "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
      "osDialog": false
}
client.sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

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.

const data = {
    algorithm: "sha256",
    data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
    pin: "1234"
}
const bulk = true;
client.sign(data, bulk).then(res => {
}, err => {
    console.error(err)
})

Bulk PIN Reset

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

client.resetBulkPin(module).then(res => {
}, err => {
    console.error(err)
})

Response will look like:

{
    "success": true,
    "data": true
}

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
client.verifyPin(data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
client.verifyPin(data, callback);

Response:

{
  "verified": true
}

Authentication

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:

var data = {
  "pin": "...",
  "algorithm": "sha256",
  "data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
}
client.authenticate(data, callback);

Response:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

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

Get valid algorithms to use for Sign or Authenticate

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

client.allAlgoRefs(callback);

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

{
    "success": true,
    "data": ["sha256"]
}

Safenet

Introduction

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

Middleware of Safenet has to be installed to be able to fully use the Safenet token.

Interface

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>;
    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>;
}

Models

Get Safenet 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.safenet(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:

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

This function call returns:

{
  "data": [
    {
      "card": {
        "atr": "3B9813400AA503010101AD1311",
        "description": [""]
      },
      "id": "57a3e2e71c48cee9",
      "name": "JC Token",
      "pinpad": false
    }
  ],
  "success": true
}

All methods for safenet will use the selected reader - identified by the reader_id.

Certificates

Exposes all the certificates publicly available on the smart card.

Root Certificate

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:

client.beid(reader_id).rootCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Authentication Certificate

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:

client.beid(reader_id).authenticationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Intermediate Certificate (citizen)

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:

client.beid(reader_id).intermediateCertificates(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Non-repudiation Certificate

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:

client.beid(reader_id).nonRepudiationCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Encryption Certificate

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:

client.beid(reader_id).encryptionCertificate(parseCertsBoolean, callback);

Response:

{
    success: true,
    data: {
        certificate?: string,
        certificates?: Array<string>,
        certificateType?: string,
        id?: string,
        parsedCertificate?: Certificate,
        parsedCertificates?: Array<Certificate>
    }    
}

Data Filter

Filter Certificates

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

var filter = [];
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 },
 "intermediateCertificates": {
  ...
 },
 "encryptionCertificate": {
  ...
 }
}

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

var filter = ['rootCertificate'];
client.safenet(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 }
}

Sign Data

Signing

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:

var filter = null;
client.safnet(reader_id).allCerts(parseCerts, { filters: filter}, callback);

Response:

{
 "rootCertificate": {
  ...
 },
 "authenticationCertificate": {
  ...
 },
 "nonRepudiationCertificate": {
  ...
 },
 "intermediateCertificates": {
  ...
 },
 "encryptionCertificate": {
  ...
 }
}

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)

Sign Hash without 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:

var data = {
      "pin":"...",
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": true
}
client.safenet(reader_id).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.

Sign Hash with pin-pad

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

var data = {
      "algorithm":"sha1",
      "data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
      "osDialog": false
}
client.safenet(reader_id).sign(data, callback);

Response is a base64 encoded signed hash:

{
  "success": true,
  "data": {
    "data" : "W7wqvWA8m9S...="
  }
}

The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.

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.

Verify PIN

Verify PIN without pin-pad

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

var data = {
      "pin":"..."
}
client.safenet(reader_id).verifyPin(data, callback);

Response:

{
  "verified": true
}

Verify PIN with pin-pad

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

var data = {}
client.safenet(reader_id).verifyPin(data, callback);

Response:

{
  "verified": true
}

Authentication

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.safenet(reader_id).authenticate(data, callback);

    Response:

    {
      "success": true,
      "data": {
        "data" : "W7wqvWA8m9S...="
      }
    }

    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 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.

Get valid algorithms to use for Sign or Authenticate

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

generic.allAlgoRefs(module, callback);

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

{
    "success": true,
    "data": ["sha1", "sha256"]
}

Troubleshooting

Windows

Error while retrieving readers

Is the smartcard service running?

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'.

DNS probe finished nxdomain error

Error during installation MSI error 2502 or 2503

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.

Antivirus

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.

ESET

If the user receives an notification that a script from the Trust1Connector is blocked as shown below:

Kaspersky

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.

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

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

Where can i find the log files

Windows

%localappdata%/Trust1Connector/

Macos

~/Library/Application Support/Trust1Team/Trust1Connector/

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

  • application/domain scoped, application types are bound to the application domain

  • OS native files and directory chooser dialogs

The File-exchange payload limit is set to 50 MB. If your needs exceed this please contact support

Configuration file

The configuration file can be found in

Notifications

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).

Context and scope

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:

Type Mapping

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).

Type subfolders

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.

Responses

The File Exchange API can be integrated using Promises or callbacks. Both are returning the same result.

Bulk File Transfer

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.

Language

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).

Interface

Objects

Enums

The following enumerators have been exported by the File Exchange container:

Classes

Function Descriptions

The following functions are available in the T1C-JS library:

Detailed Function Overview

Paging (Page interface)

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.

download

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.

Interface

Parameters

  • 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

  • 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

Output

Use Cases

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.

    • The file is downloaded to the directory of the path + relpath (recursive creation).

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.

  • End

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.

  • 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).

upload

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.

Interface

Parameters

  • 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

  • relpath: optional relative path (array of strings)

  • notifyOnCompletion: show modal info form operating system to user upon completion

Output

Returns a Blob object

listTypes

Retrieve a list of current persisted mappings given an optional entity.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted. Optional.

  • page: apply a paging to the result. Optional.

Output

listType

Retrieve a list of current mappings given an entity type context.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • type: the entity type mapping context

Output

listTypeContent

List all the content for a mapping.

Interface

Parameters

  • 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

  • page: apply a paging to the result. Optional.

Output

listContent

List all the content for a mapping given an entity context..

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • page: apply a paging to the result. Optional.

Output

existsType

Verify if a context mapping exists.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • type: the entity type mapping context

Output

existsFile

Verify if a file exists in a context mapping.

Interface

Parameters

  • 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

Output

getAccessMode

Get the access mode of a folder or file in a context mapping.

Interface

Parameters

  • 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

  • relpath: an optional relative path based on the context root folder

Output

createDir

Create a directory in a context mapping.

Interface

Parameters

  • 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

  • recursive: indicate whether the directory should be created recursively. If not and the parent directories do not exist, an error will be thrown.

Output

copyFile

Copy a file from one context mapping to another.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • fromType: the originating entity type mapping context

  • toType: the destination entity type mapping context

  • 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

Output

moveFile

Move a file from one context mapping to another.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • fromType: the originating entity type mapping context

  • toType: the destination entity type mapping context

  • 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

Output

renameFile

Rename a file in a context mapping.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • fromType: the originating entity type mapping context

  • toType: the destination entity type mapping context

  • filename: the name the of the to copy

  • relpath: an optional relative path based on the context root folder

Output

getFileInfo

Get file information of a file in a context mapping.

Interface

Parameters

  • 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

  • relpath: an optional relative path based on the context root folder

Output

createType

The initPath parameter denotes an initial path proposal from the application. Example values:

Windows

macOS

Linux

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 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

Interface

Parameters

  • 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

  • timeout: optional timeout in seconds before the folder dialog is discarded)

  • initPath: the optional initial root context path for the new type

Output

Use Cases

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.

    • 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.

      • Validation of the creation.

        • The Type is created.

    • End

createTypeDirs

Create directories for a context mapping.

Interface

Parameters

  • 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

  • modal: indicate if the folder dialog must be shown

  • timeout: optional timeout in seconds before the folder dialog is discarded)

Output

updateType

Update a context mapping. A folder dialog will be opened and a new root context path can be choosen.

Interface

Parameters

  • 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)

Output

deleteType

Delete a context mapping.

Interface

Parameters

  • entity: the entity context where the type mapping is persisted.

  • type: the entity type mapping context

Output

Error Responses

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:

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.

Model Objects

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

Get Printer module object

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.

List

An example callback:

Response:

Print

The data block needs to be base64 encoded.

An example callback:

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

Crelan

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 container supports functionality for Crelan bank cards

Get Crelan Module

Initialise a Trust1Connector client:

Get the Crelan module:

Call a function for the Crelan module:

Obtain the Reader-ID

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 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.

Reading data

Applications

List the supported applications on the Crelan card

An example callback:

Response:

Application data

The application data contains information of the holder of the card, the validity, the primary account number, ...

An example callback:

Response:

Issuer Public Key Certificate

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:

ICC Public Key Certificate

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:

Verify PIN

Verify PIN without pin-pad

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:

Verify PIN with pin-pad

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

Response:

Verify PIN - retries left

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.

Sign

  • 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

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.

Response will look like:

Error Handling

Error Object

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:

Remote loading

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 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)

  • retrieve card/card reader features

  • verify if card present

  • retrieve ATR

  • ...

Communication Flow

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.

Available functions

The following functions are available in the library:

ReaderId

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

Callback/Promise

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.

SessionID is optional

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'

Interface

Objects

Detailed Function Overview

openSession

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

The sessions are opened in shared mode

Interface

Parameters

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

Output

command

Sends a command to the reader for execution.

Interface

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

Parameters

  • tx: command-string to be executed

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

Output

ccid

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

Interface

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

Parameters

  • 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.

Output

closeSession

Closes currently open session.

Interface

closeSession(callback?: (error, data))

Parameters

  • none

Output

isPresent

Checks if the card for this session is still present.

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

Interface

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

Parameters

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

Output

atr

Retrieves the ATR for the card currently in the reader.

Interface

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

Parameters

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

Output

ccidFeatures

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

Interface

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

Parameters

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

Output

apdu

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.

Interface

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

Parameters

  • 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:

Output

Bulk Actions

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

apdus (bulk)

Executes an array of APDU calls on the current reader.

Interface

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

Parameters

  • 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:

Output

commands (bulk)

Executes an array of commands on the current reader.

Interface

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

Parameters

  • 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.

Output

Host of the web application the Trust1Connector is being used on. This property is used to make sure no collisions can happen

All model information can be found in the

Check the before signing with a defined algorithm

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.

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.

Supported version of the middleware is; Windows: 3.5.3.0 - & MacOS:

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.

You can use the following online tool to calculate the SHA256:

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:

For more information about the error codes you can check the

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.

You can use the following online tool to calculate the SHA256:

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:

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

All model information can be found in the

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 version of the middleware supported is; Mac: Mac M1: Windows:

All model information can be found in the

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.

Supported version of the middleware is; Windows: 10.2 - & MacOS:

All model information can be found in the

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;

More information can be found here;

The procedure at can be used to solved the issue.

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

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

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

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.

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:

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 method is called.

The PIN can provided/entered in the same way as

For the error codes and description, see .

Consent
clipboard.js
Clipboard APIs
64bit
32bit
3.5.3.0
PKI.js
calculate SHA256
hex to base64 converter
Error codes page
PKI.js
calculate SHA256
hex to base64 converter
64bit
32bit
10.2.97 (supports up until MacOS 10.15 at the time of integration)
6.11.9.1 (supports up until MacOS 10.15 at the time of integration)
6.17.1.0
6.12.0.0
64bit
32bit
10.2
https://www.hostinger.com/tutorials/fix-dns_probe_finished_nxdomain
https://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/windows-8-install-some-software-using-msi/48881523-1a5d-4c43-abc4-01b1ce3ebf3a
https://support.eset.com/kb2908/?locale=en_US&viewlocale=en_US
Token typings model page
Token typings model page
Token typings model page
Token typings model page
valid algorithm options
Bulk Sign Reset
Bulk Sign Reset
Bulk Sign Reset
%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

MAPPED, UNMAPPED

Use to inform the application if a Type has been mapped to an absolute path by the user.

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.

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.

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
}
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>;
}
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);
    }
}
T1CSdk.T1CClient.initialize(config).then(res => {
    client = res;
}, err => {
    console.error(error)
});
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,
}
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);
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"
}
// 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
}

Code

Description

301

Warning: the user can try twice more to verify his PIN

301

Warning: the user has only 1 retry left

301

Error: the PIN is blocked

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"
}

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.

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.

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
}
Integration in Web Applications
Print
List
Status codes / error handeling
Promise
Status codes
Core Services
Bulk PIN Reset
Verify PIN
here
The root and intermediate certificates are both stored as root certificates.
File Exchange Object Model