RC-S380 を用いたFeliCa Lite-Sへの書き込み」でFeliCa Lite-S形式のICカードへの書き込みをおこない、「PC/SC APIを用いてSuicaカードの利用履歴情報の読み取り」でWindowsで標準でサポートされるPC/SC のインタフェースでSuicaカードのをアクセスしました。今回は、PC/SC のインタフェースでFeliCa Lite-S形式のICカード「フェリカ 革製キーホルダ型 ICタグ」にデータを書き込みます。

動作環境

  • Windows 10 Professional
  • Visual Studio 2019
  • PaSoRi RC-S380

フェリカ 革製キーホルダ型 ICタグ

フェリカ 革製キーホルダ型 ICタグ (FeliCa Lite-S, フェリカライトエス) 業務用, TS-K1-NFCをamazonから購入したので、Raspberry Pi 3にRC-S380 非接触ICカードリーダー/ライター PaSoRi(パソリ)を接続してデータを書き込みました。RC-S380に置いた購入した革製キーホルダ型 ICタグを次に示します。

フェリカ 革製キーホルダ型 ICタグ

APDUコマンド仕様

PC/SCで使用するAPDUコマンドの仕様を次に示します。

Select File

Select File
byte no 項目名 指定値 説明
0 CLA FF 命令クラス FF固定
1 INS A4 Select File
2 P1 00 エリア数 00固定
3 P2 01 サービス数 01固定
4 Le 02 データサイズ 02固定
5 Data 09 Selectするサービス 指定はリトルエンディアン
6 Data 00 Selectするサービス

Read Binary

Read Binary
byte no 項目名 指定値 説明
0 CLA FF 命令クラス FF固定
1 INS B0 Read Binary
2 P1 00 Block開始位置指定 00固定
3 P2 00 Blockリスト指定 00~指定でブロックx番目を取得する
4 Le 00 00固定

Update Binary

Update Binary
byte no 項目名 指定値 説明
0 CLA FF 命令クラス FF固定
1 INS D6 Update Binary
2 P1 00 Block開始位置指定 00固定
3 P2 00 Blockリスト指定 00~指定でブロックx番目に書く
4 Lc 以降に続くデータのサイズ
5 データ 書き込みたいデータ
6 Le 00 00固定

Write Binary APDUコマンドはエラーのため使用できませんでした。

ステータスワード

「SW1:0x90、SW2:0x00」のときのみ成功を示し、それ以外の場合はつぎの実行できなかった理由を示します。

APDUステータスワード

FeliCa Lite-Sのリード/ライト関数

PC/SC APIを用いてSuicaカードの利用履歴情報の読み取り」の「ICカード読み取り関数」に示すSendCommandメソッドを次のように変更します。

  • 7行目で、Select File APDUコマンド を定義します。
  • 8行目で、Read Binary APDUコマンド を定義します。
  • 9行目で、Update Binary APDUコマンド を定義します。
void SendCommand(IntPtr hContext, string readerName)
{
    int dwResponseSize;
    byte[] response = new byte[2048];
    long lResult;

    byte[] commnadSelectFile = { 0xff, 0xA4, 0x00, 0x01, 0x02, 0x09, 0x00 }; //Select File APDUコマンド サービスコード:9
    byte[] commnadReadBinary = { 0xff, 0xb0, 0x00, 0x01, 0x00 };  // READ BINARY 2ブロック目のデータの読み込み
    byte[] commnadUpdateBinary = { 0xff, 0xd6, 0x00, 0x01, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11, 12, 13, 14, 15,0x00 }; // UPDATE BINARY

    IntPtr SCARD_PCI_T1 = GetPciT1();
    NfcApi.SCARD_IO_REQUEST ioRecv = new NfcApi.SCARD_IO_REQUEST
    {
        cbPciLength = 2048
    };
    IntPtr hCard = Connect(hContext, readerName);

    dwResponseSize = response.Length;
    lResult = NfcApi.SCardTransmit(hCard, SCARD_PCI_T1, commnadSelectFile, commnadSelectFile.Length, ioRecv, response, ref dwResponseSize);
    if (lResult != NfcConstant.SCARD_S_SUCCESS)
    {
        Debug.WriteLine("SelectFile error\n");
        return;
    }
    dwResponseSize = response.Length;
    lResult = NfcApi.SCardTransmit(hCard, SCARD_PCI_T1, commnadUpdateBinary, commnadUpdateBinary.Length, ioRecv, response, ref dwResponseSize);
    if (lResult != NfcConstant.SCARD_S_SUCCESS)
    {
        Debug.WriteLine("WriteBinary error\n");
        return;
    }
    Parse_tag(response);
    dwResponseSize = response.Length;
    lResult = NfcApi.SCardTransmit(hCard, SCARD_PCI_T1, commnadReadBinary, commnadReadBinary.Length, ioRecv, response, ref dwResponseSize);
    if (lResult != NfcConstant.SCARD_S_SUCCESS)
    {
        Debug.WriteLine("ReadBinary error\n");
        return;
    }
    Parse_tag(response);
}

作成したプログラムの実行

デバックメニューから「デバック開始」をクリックすると、作成したプログラムが実行され、出力ウインドウに次のメッセージが表示されます。

Smart Cardサービスに接続しました。
リーダー名を\0で接続した文字列: Sony FeliCa Port/PaSoRi 3.0 0 
Sony FeliCa Port/PaSoRi 3.0 0 (S/N 0206962) から、カードを読み取りました。012E4128728C7E8B
Suica履歴データ:90-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
Suica履歴データ:00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-90-00