Ocra HOTP Smartcard
The OCRA container facilitates communication with card readers with initialised OCRA applet. The T1C-JLIB client library provides function to communicate with the smart card and facilitates integration into a native or Java application for the generation of HOTP challenges. This document describes the functionality provided by the OCRA - temporary documentation - on the T1C-GCL (Generic Connector Library).
Refereces
The following standards must be taken into account:
- HOTP: An HMAC-Based One-Time Password Algorithm
- OCRA: OATH Challenge-Response Algorithm
Generation of an HOTP Value
Additional reference upon the interpretation of the HOTP challenge received from the OCRA applet:
https://tools.ietf.org/html/rfc4226#section-5.3
Resynchronization of the Counter
Additional reference upon the resynchronization of the counter:
https://tools.ietf.org/html/rfc4226#section-7.4
Get the OCRA container object
For more information on how to configure the T1C-JLIB client library see Client Configuration. Initialize a gclClient:
LibConfig conf = new LibConfig();
conf.setEnvironment(Environment.DEV);
conf.setDsUri(DS_URI);
conf.setOcvUri(OCV_URI);
conf.setGclClientUri(URI_T1C_GCL);
conf.setApiKey(API_KEY);
conf.setHardwarePinPadForced(false);
conf.setDefaultPollingIntervalInSeconds(5);
conf.setDefaultPollingTimeoutInSeconds(10);
conf.setSessionTimeout(60);
T1cClient t1cClient = new T1cClient(conf);
Obtain the GclReader object
The constructor for the Ocra container expect as the parameter to be a valid GclReader-object. A reader object 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:
List<GclReader> reader = t1cClient.getCore().getReadersWithInsertedCard();
This function call returns:
This function call returns a list of the following objects:
com.t1t.t1c.GclReader
Name | Description | Example Value | Type |
---|---|---|---|
id |
The reader ID | "707e7a6e449f2250" | java.lang.String |
name |
The reader name | "OMNIKEY CardMan 5321" | java.lang.String |
pinpad |
The presence of a hardware PIN-pad | false | java.lang.Boolean |
card |
The inserted card | see below | com.t1t.t1c.core.GclCard |
com.t1t.t1c.GclCard
Name | Description | Example Value | Type |
---|---|---|---|
atr |
Answer to Reset | "3B7F94000080318065B0850300EF120FFF829000" | java.lang.String |
description |
List of descriptions | ["Gemalto Classic V4","Juridic Person's Token (PKI)"] | java.util.List<java.lang.String> |
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 OMNIKEY CardMan 5321
, 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 container must be instantiated with the GclReader object containing the Ocra card:
OcraContainer container = t1cClient.getOcraContainer(reader);
All methods for ocra will use the selected reader - identified by the reader
-object.
Reading data
Counter
The counter on the card is incremented each time you generate a new otp with the challenge method.
String counter = container.readCounter(
// Optional PIN
"1234"
);
Response:
"12345678901234567"
Data Filter
Filter
All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:
OcraAllData allData = container.getAllData();
Response:
com.t1t.t1c.containers.smartcards.ocra.GclOcraAllData
Name | Description | Example Value | Type |
---|---|---|---|
counter |
The counter | "zMzMzMzMzN4=" | java.lang.String |
The filter can be used to ask a list of custom data containers. At the moment only the 'counter' is supported:
OcraAllData allData = container.getAllData(Collections.singletonList("counter"));
Verify PIN
When the native or Java application is responsible for showing the password input, the following request is used to verify a card holder PIN:
Boolean pinVerified = container.verifyPin("1234");
Response:
java.lang.Boolean
Verify PIN - retries left
After an unsuccesfull PIN verification, the container will throw a com.t1t.t1c.exceptions.VerifyPinException
Boolean pinVerified = container.verifyPin("1235");
The following exception will be thrown when PIN is wrong:
com.t1t.t1c.exceptions.VerifyPinException
Name | Description | Example Value | Type |
---|---|---|---|
message |
The message | "Wrong pin, 2 tries remaining" | java.lang.String |
retriesLeft |
The amount of retries left | 2 | java.lang.Integer |
Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status
.
Challenge
To generate a new OTP value, the challenge method can be called. The request requires a challenge and a PIN. The challenge is a base64 encoded bytestring .
Long otp = container.getChallengeOTP("kgg0MTQ4NTkzNZMA", "1234");
Response:
50066323