|
|
Documentation
- Installation
- Core Components
- Usage
- Normal Usage
- HThalesMSg XML definition
- Q2/JPOSEE Usage
- PCI Compliance
- Adaptation for QMUX
- Throughput and Multiple Connections
You can download the precompiled JAR file or the source file,
If you don't wanna go to the trouble of compiling it, just copy
HThales.jar somewhere in your classpath directory.
For Q2/JPOS-EE usage I Think on most of the cases you need to copy the jar file into the lib directory inside the deploy folder(the one where all your Q2 bean xml definition resides.
UPDATE : JPOS Q2 uses a seperate classloader for loading jars in deploy/lib directory.
Unfortunately, my HThalesAdaptor.class uses instanceof Operator, so it won't work for Q2 unless you compile the source along with the JPOS module and its all in one jpos-ee.jar
And don't forget to copy your Message Definition XML files, to a directory somewhere.
HThalesMsg
This is the FSDMsg style Thales Racal command parser, with a few added field type and seperator compared to the original FSDMsg, they are
Field Type : T
Represents a Thales KeyScheme+Key
Length : 16H, 1A+16H/32H/48H
Supports the keySchemes
- None/Z
Encryption of a single length DES key using ANSI X9.17 methods. Used for encryption of keys under a variant LMK, and can also be used for the import or export of keys. - U
Encryption of a double length DES key using the variant method; used for encryption of keys under a variant LMK.
- T
Encryption of a triple length DES key using the variant method; used for encryption of keys under a variant LMK.
- X
Encryption of a double length key using ANSI X9.17 methods; only available for import and export of keys. This mode is enabled within the Configure Security command.
- Y
Encryption of a triple length key using ANSI X9.17 methods; only available for import and export of keys. This mode is enabled within the Configure Security command.
the field type T will set lenght to the default lenght specified in the schema definition, until it recieves a keyscheme that overrides it.
So practically speaking for ZMK keys you use field definitions like
<field id='zmk' type='T' length='16'/>
When theres no prefix in front, it assumes a 8 byte, 16 HEXCHAR key
With specific prefix U,T,X,Y it will automatically select the correct lenght.
And this is for CVK, since the default is usually 32
<field id='cvk' type='T' length='32'/>
PS, Adding additional keyscheme for EMV and etc is trivial if you're willing to look at the source
Field Type O
For optional data, that may or may not be present, usually used in conjuction with pre separators
Seperator ES
Gives you a semicolon ';' as a separator
PreSeparators
Just like a separator, but their placed at the start of the field, usually used with optional data.
PreSeparator SS = ';'
PreSeparator SP = '%'
PreSeparator SC = 'X'19'
HThalesCore
Reponsible for creating the request, by looking up the schema definition files in the specified directory and creating connection
HThalesAdaptor
A Q2ChannelAdaptor like component that if you use a JPOS Q2 architecture will take care of keeping the connection alive and uses Java Spaces.
For normal usage, use code like
import net.hairi.Thales.*;
....................
//Function parameters String hostname, int port, String basepath, String schema
//basepath is where you store all your HThalesMsg schema xml definition file
HThalesCore core = new HThalesCore("localhost", 1234,"cfg/hsm-", "base");
HThalesMsg req = core.generateDoubleLengthKey();
try {
core.connect();
HThalesMsg rep = core.comand(req);
} catch (Exception e) { .. }
I've implemented some HSM commands in the HThalesCore as a reference guide, when you're creating your own commands with definition files your code will probably look like
Thales JC message for PINBLOCK
.........................
HThalesMsg req3 = core.createRequest("JC");
req3.set("source-tpk", "U8463435FC4B4DAA0C49025272C29B12C");
req3.set("pin-block", "028DCC093FB0471F");
req3.set("pin-block-format", "03");
req3.set("account-number", "407000025321");
try {
HThalesMsg rep = core.command(req);
} catch (Exception e) { .. }
With message definition like
File : hsm-JC.xml
<?xml version='1.0' encoding='UTF-8'?>
<schema id='JC'>
<field id='source-tpk' type='T' length='32'/>
<field id='pin-block' type='A' length='16'/>
<field id='pin-block-format' type='A' length='2'/>
<field id='account-number' type='A' length='12'/>
</schema>
And the corresponding response definition
File : hsm-resp-JD.xml
<?xml version='1.0' encoding='UTF-8'?>
<schema id='JD'>
<field id='PIN' type='A' length='5'/>
</schema>
So .....
When you need to implement a new command, just prepare the FSD defintion file.
Here is another example that makes use of the optional data field and preseparators
File : hsm-DW.xml
<?xml version='1.0' encoding='UTF-8'?>
<schema id='DW'>
<field id='zmk' type='T' length='32'/>
<field id='cvk' type='T' length='32'/>
<field id='optiondata' type='OSS' length='3'/>
<field id='trailerdata' type='OSC' length='10'/>
</schema>
File : hsm-DX.xml
<?xml version='1.0' encoding='UTF-8'?>
<schema id='DX'>
<field id='bdk' type='T' length='32'/>
<field id='kcv' type='AEOF' length='12'/>
</schema>
With code like
......................
HThalesMsg req = core.createRequest("DW");
req.set("zmk", "U1457FF6ADF6250C66C368416B4C9D383");
req.set("cvk", "6A2C67C227784BC5D8508B6BED82ECB8");
req.set("optiondata","0U1");
req.set("trailerdata","1234567890");
try {
core.connect();
HThalesMsg rep = core.command(req);
} catch (Exception e) { .. }
Thread Safety and Concurency
Unlike ISO8583 switching host that sometimes route messages to other far flung host, and messages response can arrive in different order;
I'm pretty sure that Thales HSM RG series process incoming messages synchroniously FIFO(First In First Out),
Just add a synchronized keyword/block in your code, and it should be fine.
Variable Length Field
When dealing with variable lenght fields, just browse the schema definition example so that you can implement the proper one for your needs.
For Q2 we have the HThalesAdaptor Q2 Bean, with xml deployment like this
<?xml version="1.0" ?>
<HThales-adaptor name='thales-adaptor'
class="net.hairi.Thales.HThalesAdaptor" logger="Q2">
<host>hsmhostt</host>
<port>9998</port>
<keep-alive>yes</keep-alive>
<keep-alive-interval>10000</keep-alive-interval>
<basepath>cfg/hsm-</basepath>
<in>hthales-send</in>
<out>hthales-receive</out>
<reconnect-delay>10000</reconnect-delay>
</HThales-adaptor>
You cand send message like
Space sp = SpaceFactory.getSpace();
HThalesMsg req4 = core.createRequest("DG");
req4.set("pvk-pair", "UA8B1520E201412938388191885FFA50A");
req4.set("pin", "01234");
req4.set("account-number", "407000025321");
req4.set("pvki", "1");
sp.out("hthales-send", req4);
HThalesMsg resp4 = sp.in("hthales-receive", 10000);
Or to ensure thread safety wrap it under TSpace
Space sp = SpaceFactory.getSpace();
TSpace ts = new TSpace();
HThalesMsg req4 = core.createRequest("DG");
req4.set("pvk-pair", "UA8B1520E201412938388191885FFA50A");
req4.set("pin", "01234");
req4.set("account-number", "407000025321");
req4.set("pvki", "1");
ts.out ("Request", req4);
sp.out("hthales-send", ts);
HThalesMsg resp = ts.in ("Response", 10000);
The HThalesAdaptor accepts both FSDMsg and TSpace input into its in space.
JMX is supported, so you can manage it via the JMX console for some cool stuff.
I think HThalesAdaptor should be PCI compliant.
The thing is, last time I checked TSpace and JPOS default space implementation doesn't serialize to disk. I don't know if that has changed.
Why does this matter ?, because PCI forbid any sensitive info stored in permanant media.
If it does, you need to wrap your request to other Java space implementation
6. QMUX and Thales Racal Message Trailer
No, you can't currently wrap HThalesAdaptor in a Qmux, I don't see any hard requirements for it. However since a few of you in JPOS mailing list insist on using it, my tip is, just recast FSDMsg to FSDISOMsg, and send it over the wire.
Add FSDISOMsg handling to HThales adaptor space input, and don't forget
in your FSD XML definition every last field should use the FS type, so that JPOS will ad 1C after it, after that add in the field "11" and "41" which the QMux uses.
Right, to get the max rated troughput on your Thales HSM you usually need to have multiple connections.
Luckily Java Space and JPOS Q2 provides a very straightforward way to do this.
Create 2 deployment descriptor for HThalesAdaptor with different name attribute, referencing to the same in/out space
<?xml version="1.0" ?>
<HThales-adaptor name='thales-adaptor1'
class="net.hairi.Thales.HThalesAdaptor" logger="Q2">
<host>hsmhostt</host>
<port>9998</port>
<keep-alive>yes</keep-alive>
<keep-alive-interval>10000</keep-alive-interval>
<basepath>cfg/hsm-</basepath>
<in>hthales-send</in>
<out>hthales-receive</out>
<reconnect-delay>10000</reconnect-delay>
</HThales-adaptor>
<?xml version="1.0" ?>
<HThales-adaptor name='thales-adaptor2'
class="net.hairi.Thales.HThalesAdaptor" logger="Q2">
<host>hsmhostt</host>
<port>9998</port>
<keep-alive>yes</keep-alive>
<keep-alive-interval>10000</keep-alive-interval>
<basepath>cfg/hsm-</basepath>
<in>hthales-send</in>
<out>hthales-receive</out>
<reconnect-delay>10000</reconnect-delay>
</HThales-adaptor>
And just send it through space.
Space sp = SpaceFactory.getSpace();
TSpace ts = new TSpace();
HThalesMsg req4 = core.createRequest("DG");
req4.set("pvk-pair", "UA8B1520E201412938388191885FFA50A");
req4.set("pin", "01234");
req4.set("account-number", "407000025321");
req4.set("pvki", "1");
ts.out ("Request", req4);
sp.out("hthales-send", ts);
HThalesMsg resp = ts.in ("Response", 10000);
Problem solved.
The Space will do the balancing automatically for you.
|
|