Skip to content

Latest commit

 

History

History
118 lines (88 loc) · 3.99 KB

README.md

File metadata and controls

118 lines (88 loc) · 3.99 KB

Smart Card interacting DSL for Kotlin

License Maven Central

An attempt to create Kotlin DSL around javax.smartcardio abstractions

This version is an early prototype of DSL.

Changelog

Table of Contents

Introduction

Purpose of the DSL

What you can do

Manipulate with SmartCard contents, i.e.:

  1. Read/write from/to files on the card
  2. Get information about files and directories on a card
  3. Create/delete/activate/deactivate files or directories on the card
  4. Verify PIN and another security codes
  5. Call Global Platform commands
  6. Call application specific commands (i.e. GSM application, USIM application, etc.)
  7. Anything else if there is specific APDU for that

Note that you'll have to obtain special permissions from the card issuer to perform several or all of the actions listed above!

What you can't do

  1. Develop JavaCard applications (AKA applets) in Kotlin with this DSL, you still need a JavaCard SDK for that
  2. Call APDUs which are not allowed by a card issuer

Dependency Configuration

Gradle

Groovy DSL
implementation 'com.github.brake.smart_card:smartKardDSL:0.1.0'
Kotlin DSL
implementation("com.github.brake.smart_card:smartKardDSL:0.1.0")

Maven

<dependency>
  <groupId>com.github.brake.smart_card</groupId>
  <artifactId>smartKardDSL</artifactId>
  <version>0.1.0</version>
</dependency>

Examples

Select application directory (for example ADF USIM)

fun test() {
    readers().let {
        if (it.isEmpty())  return

        with(it[0]) {
            if (waitForCardPresent(1000)) {
                try {
                    connectAuto { // CardChannel
                        APDU {  // creates APDU and transmits it immediately returning ResponseAPDU
                            ins { Instructions.Select }
                            p1 { 0 }
                            p2 { 0 }
                            dataHex { "3F00" }
                        }.assert("Invalid SW") {
                            sw1 == 0x9F
                        }
                        
                        SELECT {
                            file(MF.EF_DIR)
                            requestFCP()    
                        }.withResult {
                        // analyze FCP template and retrieve record length and number of records
                        }
                        
                        READ_RECORD {
                            recordNum(1)
                        }.withResult {  // ResponseAPDU
                            // read AID
                            val aid = data // really a part of data
                            SELECT {
                                application(aid)
                            }
                        }
                    
                        // continue in context of selected applications' DF
                    }
                } catch (e: Exception) {
                    // deal with exceptions
                }
            }
        }
    }
}

TODO

See here