DS5250と磁気ストライプカードリーダのインタフェース接続
要約
このアプリケーションノートでは、磁気ストライプカードの読取りと復号化をDS5250セキュアマイクロコントローラ上で簡単に実行する方法について説明します。この記事は、磁気ストライプカードの読取り機能と、セキュアマイクロコントローラの高度なセキュリティ機能および暗号機能を兼ね備えたアプリケーションの開発方法についても実証します。この例では、磁気ストライプカードリーダとのインタフェース接続にDS5250の評価(EV)キットを使用しています。掲載するソースコードは、他の8051ベースのマキシムマイクロコントローラに簡単に移植することが可能です。
概要
裏面に磁気符号化ストライプを備えたカードは、通常、磁気ストライプカードと呼ばれ、数多くの銀行業務やストアドバリューなどの金融アプリケーションで広く使用されています。一般的にクレジットカード、ATMカード、およびデビットカードはすべて磁気ストライプカードですが、スマートカードチップが埋め込まれているものもあります。ゲーム、コピー機、および公的輸送で使われる数多くのギフトカード、セキュリティまたはルームキーカード、ストアドバリューカードなども例に挙げられます。これらの磁気ストライプカードは、標準ISOフォーマットを使用したときの最大容量が約160バイトで、通常は大量データを保存しません。スマートカードや携帯型のフラッシュメモリドライブと違って、磁気ストライプカードの記憶容量は、カードの一般的な使用目的である金融や銀行業務のアプリケーションでは十分な容量です。さらに、磁気ストライプカードは丈夫で安価であり、内部電源が不要で、比較的読取りが簡単です。
このアプリケーションノートでは、DS5250セキュアマイクロコントローラを使用して磁気ストライプカードリーダにインタフェース接続する方法について説明します。DS5250を選択した理由は、DS5250が、販売時点情報管理(POS)端末など、磁気ストライプカードを読み取る一般的なデバイスを構築するのに必要な重要なセキュリティ機能と暗号化機能を備えているからです。
磁気ストライプカードリーダには、磁気ストライブ上の磁束をビット列に復号するという低レベルのタスクを実行するための回路が内蔵されています。DS5250はこれらのビットを文字に変換してから、データフィールドを読み取って検証するという高レベルのタスクを処理します。
ハードウェアとソフトウェアの要件
ハードウェア
このサンプルアプリケーションでは、DS5250の評価(EV)キットを以下のように改造して使用しています。
- ポート0ピン用のプルアップ抵抗パック(RN2)を取り外す
このサンプルアプリケーションでは、以下のハードウェアも必要です。
- カードリーダ - 3VのデコーダASICを備えたMagTek® Triple Trackカード読取りリーダ、製品番号21030001 rev. G以降(www.magtek.com)
- 2つのプルアップ抵抗(約10kΩ)
- リニアレギュレータ(5Vの電源から3V~3.6Vを出力可能なもの)
- テスト用の磁気ストライプカード(ATMカードやクレジットカードなど)
これらの磁気ストライプカードの詳細については、以下のMagTekリンクを使用してください。
- 3VのDelta Triple TrackカードリーダASICのドキュメントについて:www.magtek.com/documentation/public/99875258-9.02.pdf
- 磁気ストライプカードのトラック位置とフォーマットのドキュメントについて:www.magtek.com/documentation/public/99800004-1.03.pdf
- 磁気ストライブカードデータ用の文字変換テーブルについて:www.magtek.com/documentation/public/99875065-4.02.pdf
ソフトウェア
このサンプルアプリケーションはCで記述し、KeilのµVision® IDEバージョン2.40aを使用してコンパイルしました(www.keil.com/)。マキシムのマイクロコントローラツールキット(MTK)を使用して、コンパイル済みのアプリケーションをDS5250にロードしました。
アプリケーションの詳細
以下の項では、サンプルアプリケーションの実装について説明します。Cコードの完全なサンプルは、マキシムのFTPサイトからダウンロード可能です。
カードリーダの接続
MagTekカードリーダには(電源とグランドを含めて) 5つのインタフェースピンがあります。
- ピン1—STROBE
この信号は、常にカードリーダへの入力です。これはマスタマイクロコントローラによって駆動され、カードビットを同期出力し、リセットシーケンスをアサートします。 - ピン2—DATA
この信号は通常、カードリーダが出力として使用します。この信号はトラックA/B/Cからのカードデータビットを保持します。これらのデータビットはSTROBE信号によって同期出力されます。特定の状況下では(リセットシーケンスのアサート時など)、この信号はマスタマイクロコントローラによって駆動可能です。 - ピン3—VDD
カードリーダに電力を供給します(2.7V~3.6V)。 - ピン4—GND
- ピン5—GND
STROBEとDATAピンは3Vのレベルで動作するため、DS5250はこれらのピンを標準ポートのピンでじかに駆動することができません。したがって、代わりにポート0のピン(オープンドレインモードで動作)が使用されます。ピンがDS5250によってトライステートに調整されると、抵抗は信号レベルを3.6Vにプルアップします。DS5250はDATA信号をDATAラインからじかに読み取ります。DS5250のポートピンの最小VIHレベルは3VのI/Oレベルに適合するほど十分に低いからです(詳細については、DS5250データシートを参照してください)。
カードリーダは3Vのレベルで動作するため、DS5250が使用する5Vの電源からじかに動作することはできません。DS5250 EVキットは3Vの電源を供給しないため、別途リニアレギュレータ(MAX1658など)を使用してカードリーダに電源を供給します。図1を参照してください。
図1. サンプルアプリケーションの接続
リセットシーケンスの実行
最初の電源投入の後、マスタマイクロコントローラがカードリーダをリセットして初めて、カードのスキャンが可能になります。このリセットシーケンスは、各カードスキャンの後にも行う必要があります。これは、カードリーダ内部のASICメモリを消去するため、およびカードリーダ側で新しいカードスキャンを受け入れる準備を整えるためです。
カードリーダをリセットするには、マスタマイクロコントローラ(このアプリケーションではDS5250)が、以下のシーケンスにてSTROBEとDATAを駆動する必要があります(正確な電圧レベルとタイミングパラメータについては、MagTekのドキュメントを参照してください)。
- DATAとSTROBEの両方をハイ(アイドル)状態で開始します。
- DATAをローにします。
- DATAをローのままにして、STROBEをローにしてから再びハイに駆動します。
- STROBEを再びローにして、次にDATAを解放すると、DATAがフロート状態のハイになります。
- DATAをフロート状態のハイのまま、STROBEをローにしてから再びハイに駆動します。この時点でカードリーダはリセットされ、低電力待機状態に入ります。
- STROBEをローにしてから再びハイに駆動します。この動作によって、カードリーダは「起動」し、カードスキャンを受け入れる準備が整います。
// Generate a long delay for card reset and read intervals. void longDelay() { int i, j; for (i = 1; i < 5; i++) { for (j = 1; j < 5000; j++) { ; } } } // Generate a shorter delay (used between STROBE/DATA transitions). void delay() { int i; for (i = 1; i < 1000; i++) { ; } } // Release the DATA line (P0.0) and allow it to float high. void dataHigh() { P0 |= 0x01; delay(); } // Drive the DATA line (P0.0) low. void dataLow() { P0 &= 0xFE; delay(); } // Release the STROBE line (P0.1) and allow it to float high. void strobeHigh() { P0 |= 0x02; delay(); } // Drive the STROBE line (P0.1) low. void strobeLow() { P0 &= 0xFD; delay(); } void resetCardReader() { dataHigh(); strobeHigh(); longDelay(); dataLow(); // Force DATA low. longDelay(); strobeLow(); // Drive STROBE low, then high again. strobeHigh(); strobeLow(); // Drive STROBE low, then release DATA. dataHigh(); longDelay(); strobeHigh(); // Drive STROBE low and high again two more times strobeLow(); // to complete the reset and leave the card reader strobeHigh(); // in the ready state, prepared to scan a card. strobeLow(); }
カードスキャンの検出
カードリーダのリセットと起動が完了すると、カードスキャンの準備が整います。MagTekカードリーダは、スキャンするときにカードの読取りサイクル全体を実行します。したがってマスタマイクロコントローラからの介入は不要です。カードストライプ上のトラックA、トラックB、トラックCという3つのすべてのトラックの内容全体がカードリーダICに保存されます。カードの読取りサイクルが完了すると、このデータはマスタマイクロコントローラによって一度に1ビットずつ同期出力することができます。
カードリーダはハンドシェイクサイクルを経て、マスタにカード読取りの開始と完了を伝えます。
- サイクルは、STROBEがロー、DATAがフロート状態のハイ(アイドル状態)で始まります。
- 磁気ストライプがリーダヘッドを通過したことをカードリーダが検出すると、カードのスキャンを開始します。カードリーダはDATAラインをローに駆動し、マスタにカードスキャンの開始を伝えます。
- マスタは、STROBEをハイにしてから再びローに駆動することによって応答します。
- カードリーダは、再びDATAをハイに駆動します。
- カード読取りサイクルが完了すると、カードリーダは再びDATAをローに駆動します。この動作は、マスタに、カードスキャンが完了し、カードデータの同期出力の準備が整ったことを伝えます。
// Wait for the DATA line to be driven low by the card reader. void waitForDataLow() { int i = 0xFF; dataHigh(); // Make sure that DATA is floating high. while ((i & 1) == 1) { i = P0; } } .... resetCardReader(); printf("\r\n"); printf("Waiting for card swipe...\r\n"); printf("\r\n"); waitForDataLow(); // DATA low indicates that card swipe has begun. strobeHigh(); longDelay(); strobeLow(); longDelay(); waitForDataLow(); // DATA low indicates that card swipe is complete.
カードデータの読取りと復号化
カードスキャンが完了し、カードリーダのASICによってすべてのカードデータが復号されて保存された後、カードリーダはDATAラインをローに駆動します。上述のとおり、この動作は、カードデータの同期出力の準備が整ったことをDS5250に知らせます。この時点で、DS5250は、各ビットの同期出力のたびにSTROBEをハイにしてからローに駆動することによって、カードデータ内の各ビットを逐次取り出すことができます。STROBEをハイにしてからローに駆動した後、次のビットがカードリーダASICによってDATAライン上に同期出力されます。ASICは、DATAの0ビットについてはハイに駆動し、1ビットについてはローに駆動します。
// Clock a single bit value out of the card reader by driving STROBE high, // then low, and reading the DATA line. int readBit() { int i; strobeHigh(); // Drive STROBE high. strobeLow(); // Drive STROBE low (DATA line now contains bit). i = P0; if ((i & 1) == 0) { return 1; // Low on DATA line indicates a 1 bit. } else { return 0; // High on DATA line indicates a 0 bit. } }
カードリーダから同期出力される最初の16ビットは、カードリーダASICのバーションを示す「プリアンブル」です。これらのビットはカードデータを表すものではないため、アプリケーションによって削除可能です。
トラックAの変換
16ビットのプリアンブルの後、DATAライン上で同期出力される次の704ビットには、磁気ストライプカード上のトラックAから読み取られたデータが含まれます。標準ISOフォーマットを使用して符号化すると、トラックAには、英数字と他の各種記号を含む7ビットの文字セットを使用して最大76文字が格納されます。
7ビットの文字はそれぞれ、最下位ビット(LSB)から同期出力されます。最上位ビット(7番目のビット)は、カードデータの完全性を検証するために任意で使用可能なパリティビットです。パリティビットを無視すると、残りの6ビットが、トラックA上で符号化可能な64文字の1つを定義します。たとえば、000000bはスペース文字に、000001bは感嘆符に相当します。char7bit[64]文字配列を以下のコードに示します。
// 0123456789012345678901234567890123456789012345678901234567890 123 char char7bit[64] = " !'#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; // Clock out and decode a 7-bit character from the track memory, returning the // character value. 7-bit (alphanumeric) characters are found on Track A only. char read7BitChar() { int i, c; // Each character is composed of 7 bits, which we clock out of the track memory // beginning with the least significant bit. Bit 7 is parity, which is ignored. c = 0; for (i = 1; i < 128; i *= 2) { c |= (readBit() * i); } c &= 0x3F; return char7bit[c]; // Decode/return the character using the 7-bit table. } .... // Track A - 76 characters, 7 bits per alphanumberic character including parity. printf("Track A > "); for (i = 0; i < 76; i++) { putchar(read7BitChar()); } printf("\r\n\r\n"); // At this point, we have read 532 bits of the 704-bit Track A memory on the // card reader IC. Flush the remaining 172 bits. for (i = 0; i < 172; i++) { readBit(); }
トラックAに保持される実際のデータは、カードタイプによって異なります。トラックAにはさらに、アルファベット文字も含まれます。このため、トラックAは、カード所持者の名前、場合によっては住所、アカウント番号、およびその他の数値情報を保存するのによく使用されます。上記のコードが示すように、トラックBデータの同期出力の前に、トラックAメモリの704ビットのすべてを読み取る必要があります(ただし、ビットのすべてに符号化データが含まれるわけではありません)。
トラックBの変換
トラックBはトラックAと同様に符号化されますが、文字の符号化が7ビットでなく、5ビット(4ビットプラス1ビットのパリティビット)であるという点のみが違います。トラックBの文字セットには、以下のchar5bit[16]文字配列に示すとおり、数字と記号のみが含まれます。
// 0123456789012345 char char5bit[16] = "0123456789:;<=>?"; // Clock out and decode a 5-bit character from the track memory, returning the // character value. 5-bit (numeric+symbol) characters are found on Tracks B and C. char read5BitChar() { int i, c; // Each character is composed of 5 bits, which we clock out of the track memory // beginning with the least significant bit. Bit 5 is parity, which is ignored. c = 0; for (i = 1; i < 32; i *= 2) { c |= (readBit() * i); } c &= 0x0F; return char5bit[c]; // Decode/return the character using the 5-bit table. } .... // Track B - 40 characters, 5 bits per numeric/symbol character including parity. printf("Track B > "); for (i = 0; i < 40; i++) { putchar(read5BitChar()); } printf("\r\n\r\n");
トラックAの末尾と同様、トラックBメモリからの残りビットはすべて、トラックCの読取りに進む前に読み取る必要があります(トラックCを所望する場合)。コードはすでにトラックBメモリから200ビットを読み取っているため(40文字 x 5ビット)、トラックCデータにアクセスすることができるようにするには、その前にさらに504ビットを同期出力する必要があります。
トラックCの変換
トラックCはトラックBと同じ方法で符号化され、同じ文字セットを使用し、7ビットの最大107文字を符号化します。トラックCはもともと、オフラインの金融取引をサポートするために上書き可能なデータエリアを含むことを意図していましたが、通常は使用されません。大部分の磁気ストライプカードでは、トラックCに符号化データは含まれません。
結論
磁気ストライプカードは、金融、アクセス制御、行政機関、およびストアドバリューなどの広範囲なアプリケーションで使用されています。DS5250のEVキットに簡単なMagTekカードスキャンリーダと、少しの補助用ハードウェアを追加することによって、磁気ストライプカード読取り機能と、セキュアマイクロコントローラの高度なセキュリティ技術および暗号化技術を併せ持ったアプリケーションの開発が可能です。KeilのµVision Cコンパイラを使用することによって、磁気ストライプカードの読取りと復号化を実証するアプリケーションをDS5250セキュアマイクロコントローラ上に簡単に実装することができます。
注:DS5250セキュアマイクロコントローラは、そのセキュアな性質上、米国輸出法によって管理されています。データシートやユーザガイドなどのDS5250のドキュメントにアクセスするには、秘密保持契約(NDA)が必要です。ただし、このアプリケーションノートとソースコードは自由に利用可能であり、他の8051ベースのマキシムマイクロコントローラに容易に移植可能です。