Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Tuesday, November 29, 2022

PC/SC sample in TypeScript (Deno)

To continue the list of PC/SC wrappers initiated in 2010 with "PC/SC sample in different languages" I now present a new sample code in Deno a modern runtime for JavaScript and TypeScript.

pcsc-deno

The wrapper is available at https://github.com/cryptographix/pcsc-deno and https://deno.land/x/pcsc

The author is Sean Michael Wykes.

The license is MIT.

I used version 0.4.
This version includes the fixes I proposed for GNU/Linux.

Deno

From Wikipedia Deno article:

Deno is a runtime for JavaScript, TypeScript, and WebAssembly that is based on the V8 JavaScript engine and the Rust programming language. Deno was co-created by Ryan Dahl, who also created Node.js.

Deno explicitly takes on the role of both runtime and package manager within a single executable, rather than requiring a separate package-management program.


Installation

Installation is very easy. First install Deno as documented in https://deno.land/#installation

The PC/SC wrapper will be downloaded and installed automatically at run time.

Source code

import {
  CommandAPDU,
  ContextProvider,
  ISO7816,
  PCSC,
} from 'https://deno.land/x/pcsc/mod.ts';

try {
  // establish a PC/SC context
  const context = ContextProvider.establishContext();

  // get all available readers
  const readers = context.listReaders();

  for (const reader of readers) {
    console.log(`Using reader: ${reader.name}`);
    if (reader.isMute) {
      console.log(`Reader ${reader.name}: MUTE`);
    } else if (reader.isPresent) {
      // connect
      const card = await reader.connect();

      // send Select Applet APDU
      const selectApplet = CommandAPDU
        .from([ISO7816.CLA.ISO, ISO7816.INS.SelectFile, 0x04, 0x00]) // ISO SELECT
        .setData([0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01]);

      const resp = await card.transmitAPDU(selectApplet);

      // check for 0x90 0x00
      if (resp.SW == ISO7816.SW.SUCCESS) {
        // success ..
        console.log(`Reader ${reader.name}: applet successfully selected`);

        // send Test APDU
        const command = CommandAPDU
          .from([ISO7816.CLA.ISO, 0, 0, 0]);

        const resp = await card.transmitAPDU(command);
        if (resp.SW == ISO7816.SW.SUCCESS) {
          // success ..
          console.log(`Reader ${reader.name}: Test command successful`);

          // convert from bytes to string and display
          console.log(String.fromCharCode.apply(null, resp.data));
        } else {
          // something went wrong ..
          console.error(
            `Reader ${reader.name}: error SW=${resp.SW.toString(16)}`,
          );
        }
      } else {
        // something went wrong ..
        console.error(
          `Reader ${reader.name}: error SW=${resp.SW.toString(16)}`,
        );
      }

      // unpower and disconnect
      await card.disconnect(PCSC.Disposition.UnpowerCard);
    } else {
      console.log(`Reader ${reader.name}: NO CARD`);
    }
  }
  // release the PC/SC context
  context.shutdown();
} catch (e: PCSCException) {
  console.log(e, "error");
}


Output

$ deno run --unstable --allow-ffi blog.ts
Using reader: Gemalto PC Twin Reader (F8345B4A) 00 00
Reader Gemalto PC Twin Reader (F8345B4A) 00 00: applet successfully selected
Reader Gemalto PC Twin Reader (F8345B4A) 00 00: command successful
Hello world!


Conclusion

Nothing special to say. Thanks Sean for the wrapper.

If you work on a Free Software PC/SC wrapper that is not yet in my list please let me know.