Tuesday, July 1, 2014

Host Card Emulation Series: HCE Virtual Card Life Cycle Management

HCE has introduced a new and powerful way to create, issue and manage virtual cards stored in the cloud. The value of HCE is clear but with that recognition comes a great deal of other questions. One of the most common questions is that surrounding virtual card life cycle management. This blog post will discuss one tools made available by SimplyTapp to manage your virtual card in the cloud in the SimplyTapp system.


SimplyTapp offers STBridge as tool to manage card life cycle. STBridge allows an issuer to connect to a virtual card instance in the SimplyTapp cloud.

STBridge is used to communicate APDUs, and other GP commands, to a specific virtual card residing in the cloud platform. STBridge supports standard GPJ shell commands.

STBridge packaged as an executable jar (STBridge) and can be executed in the following format:

java -jar STBridge.jar -ck consumer_key -cs consumer_secret -at access_token_to_card -ts access_token_secret [-s jcsh_script_to_run

STBridge Paramater list:

-ck the issuer consumer key
-cs the issuer consumer secret
-at the card access token
-ts the card access token secret

There are various ways for obtaining the parameters from a virtual card in cloud needed to execute STBridge.
This example we are we are working with a previously create virtual card.

Managing An Active Card

Appending scripts to the STBridge.jar executable file allows one to manage card life cycle. The following are examples of how to manage card life cycle.

Card is personalized by running a personalization (perso) script.
After perso script is executed, the card is in activated state.

Post card personalization, you can connect to card and  run any various card management scripts. Activating an activated card does nothing and deactivating a deactivated card does not change the state of the card, but scripts will execute.
The following are examples of executing card management scripts on a  active virtual card in the cloud.

Deactivate Card.

vcbp_deactivate_card.jcsh is script to deactivate the card. 
After running the script, the card agent is disabled from performing contact-less transactions.  







Activate card

vcbp_activate_card.jcsh is script to activate the card again. 
After running the script, the card agent is enabled to perform contact-less transactions. 

Terminate card

vcbp_terminate_card.jcsh is script to terminate the card.
 After running the script, the card agent is disabled from performing contact-less transaction. The card agent does not load anymore after refreshing/restarting the wallet. This is like a kill switch, the state cannot be changed from terminated.  

Running vcbp_terminate_card script updates the card state in the database to "dead". 
Once a card is terminated it is marked as dead and can not be recovered to active state from  the data base.

The complete STBridge tutorial can be found at:  http://wiki.simplytapp.com/utilities-resources/stbridge/stbridge-guide

3 comments:

  1. Hi Tom, thanks for the blog on HCE. I am using SimpllyTapp sdk as given in http://blog.simplytapp.com/2014/10/the-absolute-simplest-hce-application.html . But am facing 2 issues, one is a crash whose stacktrace is given below

    W/dalvikvm( 9324): threadid=17: thread exiting with uncaught exception (group=0x41efec08)
    D/MainActivity( 9324): Account is Disabled cardId=6164 code=24
    D/MainActivity( 9324): Account is Disabled cardId=6164 code=24
    E/AndroidRuntime( 9324): FATAL EXCEPTION: Thread-2714
    E/AndroidRuntime( 9324): Process: com.example.sampletapp, PID: 9324
    E/AndroidRuntime( 9324): java.lang.NullPointerException
    E/AndroidRuntime( 9324): at com.simplytapp.cardagent.c.run(SourceFile:1794)
    E/AndroidRuntime( 9324): at java.lang.Thread.run(Thread.java:841)
    W/ActivityManager( 3042): Force finishing activity com.example.sampletapp/.MainActivity
    I/CardAgent( 9324): activated, tGetAccountParams is still accessing remote card applet, waiting...
    I/ServiceKeeper( 3042): In getseinfo pid = 3042 uid = 1000 seinfo= system
    D/CrashAnrDetector( 3042): processName: com.example.sampletapp
    D/CrashAnrDetector( 3042): broadcastEvent : com.example.sampletapp data_app_crash
    W/ApplicationPackageManager( 3042): getCSCPackageItemText()
    V/SmartFaceService - 3rd party pause( 3042): onReceive [android.intent.action.ACTIVITY_STATE/com.example.sampletapp/pause]
    D/SSRMv2:CustomFrequencyManagerService( 3042): acquireDVFSLockLocked : type : DVFS_MIN_LIMIT frequency : 1200000 uid : 1000 pid : 3042 pkgName : ACTIVITY_RESUME_BOOSTER@4
    W/ActivityManager( 3042): mDVFSHelper.acquire()

    In another issue, am trying you read card data using SoftPcd as below but transceiveWithCard() function is returning same value 6F00 in all the cases. Your help would be greatly appreciated.
    SoftPcd softPcd = new SoftPcd((short)5000);
    try {
    virtualCard.transactWithSoftPcd(softPcd);
    } catch (IOException e) {
    e.printStackTrace();
    }
    try {
    softPcd.connect();
    byte[] apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xA4,0x04,0x00,0x05,(byte)0x32,0x50,0x41,0x59,(byte)0x2E});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xA4,0x04,0x00,0x07,(byte)0xA0,0x00,0x00,0x02,0x77,0x10,0x10,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{(byte)0x80,(byte)0xA8,0x00,0x00,0x15,(byte)0x83,0x13,(byte)0xD0,(byte)0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x01,0x01,0x24,0x01,0x24,0x02,0x66,0x33,(byte)0x82,0x01,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x0C,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x14,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x02,0x14,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x03,0x14,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x04,0x14,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x1C,0x00});
    apdu = softPcd.transceiveWithCard(new byte[]{(byte)0x80,(byte)0xAE,(byte)0x80,0x00,0x2A,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,
    0x00,(byte)0x80,0x00,(byte)0x80,0x00,0x01,0x24,0x13,0x06,0x27,0x00,0x02,0x66,0x33,(byte)0x82,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00});
    softPcd.disconnect();
    } catch (IOException e) {
    e.printStackTrace();
    }

    Thanks,
    Pradeep.

    ReplyDelete