内容の確かさには万全を期しておりますが、リバースエンジニアリングの性質上、不正確な結果が含まれている場合がありますので、ご了承ください。
本文書では、特筆ない限り以下が前提です。
FeliCaは、交通系ICカードを筆頭に多くのSF(ストアードフェア)型電子マネーや身分証明書等に使用されている一方、その仕様において最も重要な暗号に関する仕様は非公開とされており、広く知られていません。暗号に関するセキュリティは、公にされ広く専門家が検証してこそ安全性が担保されるものです。このため、本文書ではFeliCaの隠された仕様を明らかにします。本文書は、JIS X 6319-4[4]、FeliCaカード ユーザーズマニュアル 抜粋版(以下、U-MAN)[3]、felica-tool[2]およびProxmark3[1]を大いに参考にしています。より詳しい情報を知りたい方はこれらも併せてご確認ください。
FeliCaは、ソニー株式会社が開発した非接触型ICカード技術の一つで、NFC Type-Fとも呼ばれます。市場にある実装としてはFeliCa StandardとFeliCa Lite-Sがあります。本文書では、前者を取り扱います。
カードとカードリーダとの間の通信プロトコルを説明します。ただし、すべてが公になっている物理層およびデータリンク層の説明は割愛し、アプリケーション層のみを取り扱います。
コマンドパケットのデータ構造を以下に示します。(表3.1)
| オフセット | 長さ | 項目 |
|---|---|---|
| 0x00 | 0x01 | コマンドコード |
| 0x01 | 可変 | コマンドデータ |
コマンドの種類を識別するための1バイトの値です。
コマンドの処理指示を規定するデータで、コマンドごとに形式が異なります。
レスポンスパケットのデータ構造を以下に示します。(表3.2)
| オフセット | 長さ | 項目 |
|---|---|---|
| 0x00 | 0x01 | レスポンスコード |
| 0x01 | 可変 | レスポンスデータ |
レスポンスの種類を識別するための8ビットの値です。
レスポンスの処理結果を規定するデータで、コマンドごとに形式が異なります。
各コマンドの概要ならびにコマンドコードおよびレスポンスコードを以下に示します。(表3.3)ただし、表中ではコマンドコードをCC、レスポンスコードをRCと表記します。また、まだ知られていないコマンドが存在している可能性があります。
Pollingコマンドのレスポンスデータとして取得できる製造ID(IDm)および製造パラメータ(PMm)を説明します。
IDmは、カードリーダがカードを識別するためのIDです。カード内に複数のシステムが存在する場合、システムごとにIDmが異なります。
IDmのデータ構造を以下に示します。(表3.4)ただし、製造者コードの先頭1バイトの上位4ビットはカード内でのシステム番号を示します。
| オフセット | 長さ | 項目 |
|---|---|---|
| 0x00 | 0x02 | 製造者コード |
| 0x02 | 0x06 | カード識別番号 |
PMmのデータ構造を以下に示します。(表3.5)ただし、ROM種別およびIC種別を合わせてICコードといいます。
| オフセット | 長さ | 項目 |
|---|---|---|
| 0x00 | 0x01 | ROM種別 |
| 0x01 | 0x01 | IC種別 |
| 0x02 | 0x06 | 最大応答時間パラメータ |
FeliCaの内部は、システム・エリア・サービス・ブロックという階層構造になっています。システムはエリアを内包し、エリアは子エリアまたはサービスを内包し、サービスはブロックを内包します。いずれも1枚のカードに複数存在することができます。このうち、システム・エリア・サービスはディレクトリのようなメタデータで、ブロックは実際のデータを格納する領域です。これらをまとめてノードと呼びます。ノードにはそれぞれを表すコードがあります。いずれのノードの存在もブロックを消費します。
システムは、論理的なカードの単位であり、階層構造の最上位にあります。システム(ノード)を表すコードは0xFFFFです。システムには、以下のシステム定義情報が定義されています。
システムコードは2バイトの値です。紛らわしいですが、システム(ノード)を表すコードとシステムコードは異なる概念です。システムコードには、例えば以下のようなものがあります。(表4.1)
| システムコード | 名称 |
|---|---|
| 0x0003 | 鉄道サイバネティクス領域 |
| 0x80CD | フリー領域 |
| 0xFE00 | 共通領域 |
| 0xFE0F | 管理領域 |
発行ID情報は、各8バイトの発行ID(IDi)と発行パラメータ(PMi)からなります。これは、Authentication2コマンドまたはAuthentication2 v2コマンドで相互認証を成功させるとレスポンスデータから得ることができます。IDiを特定のアルゴリズムで文字列に変換すると、鉄道サイバネティクス規格の交通系ICカードの裏面右下に記載されているID番号になります。
システム鍵は、DES暗号方式では8バイトの値です。AES暗号方式の場合は16バイトの値です。
システム鍵バージョンは2バイトの値です。
詳細不明です。
カードが、Pollingコマンドを受信したり、現在操作されているシステムのものとは異なるIDm宛のコマンドパケットを受信したりした場合、現在操作されているシステムが切り替わりMode0にリセットされます。ただし、Authentication1、Authentication1 v2または Internal Authenticate and Readコマンドが成功し、システム切り替えが発生した場合にはMode1になります。
エリアは、システムまたは少なくとも1つの親エリアに内包されます。エリアには、以下のエリア定義情報が定義されています。
エリアコードは2バイトの値です。第6ビットから第15ビットがエリア番号、第0ビットから第5ビットがエリア属性(表4.2)を示します。エリアコードはカード内におけるエリアの論理的な始点をも示します。
| エリア属性 | 値 |
|---|---|
| 子エリア作成可能エリア | 0b000000 |
| 子エリア作成不可能エリア | 0b000001 |
カード内におけるエリアの論理的な終点です。
エリアに割り当てられているブロックの数です。
エリア鍵は、DES暗号方式では8バイトの値です。AES暗号方式の場合は16バイトの値です。
エリア鍵バージョンは2バイトの値です。
詳細不明です。
システムには、必ず領域が0x0000から0xFFFEまでのエリア0が含まれます。
サービスは、少なくとも1つのエリアに内包されます。サービスには、以下のサービス定義情報が定義されています。
サービスコードは2バイトの値です。第6ビットから第15ビットがサービス番号、第0ビットから第5ビットがサービス属性(表4.3)を示します。サービスコードはカード内におけるサービスの論理的な位置をも示します。
サービスに割り当てられているブロックの数です。
サービス鍵は、DES暗号方式では8バイトの値です。AES暗号方式の場合は16バイトの値です。
サービス鍵バージョンは2バイトの値です。
リミットパースサービスオプションまたはMACつき通信オプションが搭載された製品でのみ設定されます。
複数のサービスコードで同じブロック群を管理することをオーバーラップするといい、同一システム内で同一サービス番号をもつサービスをオーバーラップしたサービスをオーバーラップサービスといいます。U-MAN[3]の「オーバーラップサービス」の節にある、オーバーラップの例を示した図が理解を助けます。
ブロックはカード内の不揮発性メモリにおけるデータの実体を16バイト単位に分割したものです。メタデータを格納する以外のブロックはサービスごとに一定数が割り当てられ、サービスを内包するエリアがその割り当て総数を管理します。U-MAN[3]の「エリア」の節にある、エリアによるブロック数管理を示した図が理解を助けます。
カードには、Mode0からMode3までの状態(モード)が存在します。カードで実行できるコマンドは、これにより制限されています。電源断の状態から電源が供給されると、Mode0になります。Mode1以上にはDES暗号方式、AES暗号方式またはMACつき通信方式の区分があり、それぞれAuthentication1、Authentication1 v2またはInternal Authenticate and Readコマンドを実行するとMode1に遷移します。
DES暗号方式およびAES暗号方式では、Mode1においてAuthentication2またはAuthentication2 v2コマンドを実行すると該当方式のMode2に遷移します。Mode2では、相互認証が必要なコマンド群(Read, Write, Read v2, Write v2等)を実行できます。発行系コマンドを実行すると、該当方式のMode3に遷移します。
一方、MACつき通信方式にはMode2およびMode3が存在しません。Mode1で実行できるのはExternal Authenticate and Writeコマンドであり、これを実行するとMode0に戻ります。
Mode0以外に遷移すると、カードはPollingコマンドを受け付けなくなります。ただし、システム切り替えのために別システムを指定したPollingコマンドは、いずれのモードでも実行できます。また、いずれのモードにおいてもReset ModeコマンドによりMode0に遷移します。現在のモードは、Request Responseコマンドで確認できます。より詳細な情報は、U-MAN[3]の「モード」の節を参照してください。
コマンドに与えるパラメータとコマンドの詳細について述べます。ただし、コマンドの詳細は、ページ数の都合で一部コマンドを省略します。
ブロックリストは、アクセス対象となるサービスおよびブロック番号を特定するための、ブロックリストエレメントの集合です。ブロックリストエレメントには、長さが2バイトのもの(表6.1)と3バイトのもの(表6.2)があります。ただし、表中のオフセットおよび長さはビット単位です。
| オフセット | 長さ | 項目 |
|---|---|---|
| 0 | 1 | 長さフラグ(0b1) |
| 1 | 3 | アクセスモード |
| 4 | 4 | サービスコードリスト順番 |
| 8 | 8 | ブロック番号・鍵バージョン |
| オフセット | 長さ | 項目 |
|---|---|---|
| 0 | 1 | 長さフラグ(0b0) |
| 1 | 3 | アクセスモード |
| 4 | 4 | サービスコードリスト順番 |
| 8 | 16 | ブロック番号・鍵バージョン(リトルエンディアン) |
ブロックリストエレメントが対象とするノードへのアクセス方法を指定します。(表6.3)
| アクセスモード | 値 |
|---|---|
| パースサービスへのキャッシュバックアクセス以外 | 0b000 |
| パースサービスへのキャッシュバックアクセス | 0b001 |
| 鍵変更 | 0b100 |
Pollingコマンドは、カードリーダがカードを捕捉および特定するためのコマンドです。指定したシステムコードを持つシステムのIDmおよびPMmが取得できます。
Pollingコマンドパケットのデータ構造を以下に示します。(表6.4)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x00 |
| 0x01 | 0x02 | システムコード (x) | 0x0000 ≤ x ≤ 0xFFFF (ただし、各バイト0xFFはワイルドカード。) ビッグエンディアン |
| 0x03 | 0x01 | リクエストコード | 0x00: 要求なし、0x01: システムコード要求、0x02: 通信性能要求 |
| 0x04 | 0x01 | 応答可能な最大スロット数の指定 | 0x00, 0x01, 0x03, 0x07, 0x0F (詳細はU-MAN[3]の「Polling」の節にある、タイムスロット規定の表を参照) |
Pollingレスポンスパケットのデータ構造を以下に示します。(表6.5)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x01 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x08 | PMm | - |
| 0x11 | 0x02 | リクエストデータ | コマンドにおけるリクエストコードが0x00以外であり、かつ製品が対応するリクエストコードが指定された場合のみ返送 |
対応していないリクエストコードを指定した場合、レスポンスパケットにリクエストデータは付加されません。リクエストコードを指定してもリクエストデータが返送されない場合があることを前提に実装してください。
Request Serviceコマンドは、エリアやサービスの存在確認と鍵バージョンを取得するためのコマンドです。
Request Serviceコマンドパケットのデータ構造を以下に示します。(表6.6)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x02 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ノード数 (n) | 0x01 ≤ n ≤ 0x20 |
| 0x0A | 2n | ノードコードリスト | リトルエンディアン |
Request Serviceレスポンスパケットのデータ構造を以下に示します。(表6.7)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x03 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ノード数 (n) | 0x01 ≤ n ≤ 0x20 |
| 0x0A | 2n | ノード鍵バージョンリスト | ただし、ノードが存在しない場合には0xFFFF。リトルエンディアン |
Request Responseコマンドは、カードの存在とモードを確認するためのコマンドです。
Request Responseコマンドパケットのデータ構造を以下に示します。(表6.8)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x04 |
| 0x01 | 0x08 | IDm | - |
Request Responseレスポンスパケットのデータ構造を以下に示します。(表6.9)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x05 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | モード (n) | 0x00 ≤ n ≤ 0x03 |
Read Without Encryptionコマンドは、サービス属性が認証不要のサービスからブロックデータを読み出すためのコマンドです。
Read Without Encryptionコマンドパケットのデータ構造を以下に示します。(表6.10)
Read Without Encryptionレスポンスパケットのデータ構造を以下に示します。(表6.11)
Write Without Encryptionコマンドは、サービス属性が認証不要のサービスにブロックデータを書き込むためのコマンドです。
Write Without Encryptionコマンドパケットのデータ構造を以下に示します。(表6.12)
Write Without Encryptionレスポンスパケットのデータ構造を以下に示します。(表6.13)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x09 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x0A | 0x01 | ステータスフラグ2 | 0x00: 正常 |
Search Service Codeコマンドは、エリアコードとサービスコードを取得するためのコマンドです。
Search Service Codeコマンドパケットのデータ構造を以下に示します。(表6.14)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x0A |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x02 | ノードインデックス | 0x0000 ≤ n ≤ 0xFFFF リトルエンディアン |
Search Service Codeレスポンスパケットのデータ構造を以下に示します。(表6.15)
ノードインデックスを0から順に増やしながら本コマンドを実行し、レスポンスのノードコードが0xFFFFとなった時点を終端として、カード内のノードを走査できます。
Request System Codeコマンドは、カード内に登録されているシステムコードを取得するためのコマンドです。
Request System Codeコマンドパケットのデータ構造を以下に示します。(表6.16)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x0C |
| 0x01 | 0x08 | IDm | - |
Request System Codeレスポンスパケットのデータ構造を以下に示します。(表6.17)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x0D |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | システムコード数 (n) | - |
| 0x0A | 2n | システムコードリスト | システム0から順に列挙。ビッグエンディアン。 |
Request Block Informationコマンドは、指定したノードに割り当てられているブロック数を取得するためのコマンドです。モバイルFeliCaのみ対応しています。
Request Block Informationコマンドパケットのデータ構造を以下に示します。(表6.18)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x0E |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ノードコード数 (n) | - |
| 0x0A | 2n | ノードコードリスト | リトルエンディアン |
Request Block Informationレスポンスパケットのデータ構造を以下に示します。(表6.19)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x0F |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ブロック情報数 (n) | - |
| 0x0A | 2n | ブロック情報リスト | 各ノードに割り当てられているブロック数を示す |
Authentication1コマンドは、DES方式でカード側認証チャレンジを開始するためのコマンドです。
Authentication1コマンドパケットのデータ構造は、表7.1を参照してください。
Authentication1レスポンスパケットのデータ構造は、表7.3を参照してください。
Authentication2コマンドは、DES方式の相互認証を完了するためのコマンドです。
Authentication2コマンドパケットのデータ構造は、表7.2を参照してください。
Authentication2レスポンスパケットのデータ構造は、表7.4を参照してください。
Readコマンドは、相互認証後のDESセッションでブロックデータを読み出すためのコマンドです。
Readコマンドの暗号化前内部ペイロード構造は、表7.12を参照してください。
Readレスポンスの暗号化前内部ペイロード構造は、表7.13を参照してください。
Writeコマンドは、相互認証後のDESセッションでブロックデータを書き込むためのコマンドです。
Writeコマンドの暗号化前内部ペイロード構造は、表7.14を参照してください。 アクセスモード0b100(鍵変更)のブロックデータに格納する鍵変更パッケージは、表7.16および同節の生成アルゴリズムを参照してください。
Writeレスポンスの暗号化前内部ペイロード構造は、表7.15を参照してください。
Get Node Propertyコマンドは、ノードプロパティを取得するためのコマンドです。リミットパースサービスオプションまたはMACつき通信オプションのノードプロパティが取得できます。本コマンドは、一部のAESカード製品およびAES/DESカード製品にのみ搭載されています。
Get Node Propertyコマンドパケットのデータ構造を以下に示します。(表6.20)
Get Node Propertyレスポンスパケットのデータ構造を以下に示します。(表6.21)
取得対象に0x00(リミットパースサービス)を指定した場合のノードプロパティのデータ構造を以下に示します。(表6.22)
取得対象に0x01(MACつき通信有効サービス)を指定した場合のノードプロパティは、MACつき通信有効フラグ1バイトのみです。値は0x01が有効、0x00が無効を表します。
Request Service v2コマンドは、暗号方式識別子と鍵バージョン情報を取得するためのコマンドです。
Request Service v2コマンドパケットのデータ構造を以下に示します。(表6.23)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x32 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ノード数 (n) | 0x01 ≤ n ≤ 0x20 |
| 0x0A | 2n | ノードコードリスト | リトルエンディアン |
Request Service v2レスポンスパケットのデータ構造を以下に示します。(表6.24)
Get System Statusコマンドは、システムごとの設定状態を取得するためのコマンドです。
Get System Statusコマンドパケットのデータ構造を以下に示します。(表6.25)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x38 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x02 | 予約領域 | 0x0000 |
Get System Statusレスポンスパケットのデータ構造を以下に示します。(表6.26)
フラグおよびデータの意味は詳細不明です。
Request Specification Versionコマンドは、カードOSのバージョンを取得するためのコマンドです。
Request Specification Versionコマンドパケットのデータ構造を以下に示します。(表6.27)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x3C |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x02 | 予約領域 | 0x0000 |
Request Specification Versionレスポンスパケットのデータ構造を以下に示します。(表6.28)
オプションバージョンリストの各要素の割り当てを以下に示します。(表6.29)
基本バージョンおよび各オプションバージョンは、いずれも2バイトのデータです。上位4ビットは0b1000固定であり、残りの12ビットがBCD形式のバージョン値を表します。例えば、バージョン5.0.0は0x500となります。オプションの有無およびバージョンの値は製品ごとに異なります。
Reset Modeコマンドは、モードをMode0にリセットするためのコマンドです。
Reset Modeコマンドパケットのデータ構造を以下に示します。(表6.30)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x3E |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x02 | 予約領域 | 0x0000 |
Reset Modeレスポンスパケットのデータ構造を以下に示します。(表6.31)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x3F |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x0A | 0x01 | ステータスフラグ2 | 0x00: 正常 |
Authentication1 v2コマンドは、AES方式でカード側認証チャレンジを開始するためのコマンドです。
Authentication1 v2コマンドパケットのデータ構造は、表7.6を参照してください。
Authentication1 v2レスポンスパケットのデータ構造は、表7.8を参照してください。
Authentication2 v2コマンドは、AES方式の相互認証を完了するためのコマンドです。
Authentication2 v2コマンドパケットのデータ構造は、表7.7を参照してください。
Authentication2 v2レスポンスパケットのデータ構造は、表7.9を参照してください。
Read v2コマンドは、相互認証後のAESセッションでブロックデータを読み出すためのコマンドです。
Read v2コマンドの暗号化前内部ペイロード構造は、表7.12を参照してください。
Read v2レスポンスの暗号化前内部ペイロード構造は、表7.13を参照してください。
Write v2コマンドは、相互認証後のAESセッションでブロックデータを書き込むためのコマンドです。
Write v2コマンドの暗号化前内部ペイロード構造は、表7.14を参照してください。 鍵変更(アクセスモード0b100)はWrite v2では有効ではありません。
Write v2レスポンスの暗号化前内部ペイロード構造は、表7.15を参照してください。
Register Issue IDコマンドは、発行ID関連情報を登録するための発行系セキュアコマンドです。
Register Issue IDコマンドの暗号化前内部ペイロード構造は、表7.17を参照してください。
Register Issue IDレスポンスの暗号化前内部ペイロードは、ステータスフラグ1/2に加え、成功時のみ残りブロック数(2バイト)を返します。
Register Areaコマンドは、エリアを登録するための発行系セキュアコマンドです。
Register Areaコマンドの暗号化前内部ペイロード構造は、表7.18を参照してください。
Register Areaレスポンスの暗号化前内部ペイロードは、ステータスフラグ1/2の2バイトです。
Register Serviceコマンドは、サービスを登録するための発行系セキュアコマンドです。
Register Serviceコマンドの暗号化前内部ペイロード構造は、表7.19を参照してください。
Register Serviceレスポンスの暗号化前内部ペイロードは、ステータスフラグ1/2に加え、成功時のみ残りブロック数(2バイト)を返します。
Change System Blockコマンドは、発行系コマンドの結果を確定するための発行系セキュアコマンドです。
Change System Blockコマンドの暗号化前内部ペイロード構造は、表7.20を参照してください。
Change System Blockレスポンスの暗号化前内部ペイロードは、ステータスフラグ1/2の2バイトです。
ステータスフラグは、コマンド処理の結果を表す値で、ステータスフラグ1とステータスフラグ2からなります。
ステータスフラグ1は、コマンド処理の成否やエラーが発生したブロック位置またはサービス位置を示します。(表6.32)
| 値 | 意味 |
|---|---|
| 0x00 | 正常終了 |
| 0xFF | コマンドパケットにリストを含まないコマンドでのエラーまたはリストに依存しないエラー |
| 上記以外 | エラーが発生したリスト上の位置 |
エラーが発生した位置の表現形式は製品によって2種類あり、いずれであるかはステータスフラグ1の値だけでは判別できません。(表6.33)例えば、ブロックリストの10番目に指定したノードでエラーが発生した場合、順番形式では0x0Aを、ビットマップ形式では0x02を返します。
ステータスフラグ2は、エラーの詳細内容を示します。(表6.34)また、すべての製品で共通の仕様ではない「カード固有仕様」があります。(表6.35)
0x71は警告であるため、書き込み処理自体は実行されます。書き換え回数の上限値は製品ごとに異なり、このときステータスフラグ1が0x00となる製品と0xFFとなる製品があります。
Authentication1コマンドパケットのデータ構造を以下に示します。(表7.1)
Authentication2コマンドパケットのデータ構造を以下に示します。(表7.2)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x12 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x08 | チャレンジ2B | 8バイト |
Authentication1レスポンスパケットのデータ構造を以下に示します。(表7.3)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x11 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x08 | チャレンジ1B | 8バイト |
| 0x11 | 0x08 | チャレンジ2A | 8バイト |
Authentication2レスポンスパケットのデータ構造を以下に示します。(表7.4)本レスポンスはIDmを含まず、レスポンスコードに続く部分の全体が暗号化されています。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x13 |
| 0x01 | 0x20 | 暗号化ペイロード | 乱数R2を鍵とするDES-CBC(IV=0)で暗号化されている。復号後の構造は表7.5を参照 |
復号後のペイロードのデータ構造を以下に示します。(表7.5)
DES相互認証に用いる主要パラメータは以下で導出します。
システム鍵をKsys、エリア鍵列をKarea,i、サービス鍵列をKsrv,jとすると、


でグループサービス鍵Kgroupとユーザサービス鍵Kuserを得ます。
IDmを8バイトベクトルとし、


を計算します。
2-key 3DES(鍵順K1-K2-K1)で乱数を交換します。R1,R2を乱数とすると、


となります。
Authentication2の平文は

です。ここでTIDはR1の後半6バイトを用います。発行ID情報として用いるデータは後半16バイトのIDi(8) ∥ PMi(8)です。
Authentication1 v2コマンドパケットのデータ構造を以下に示します。(表7.6)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x40 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x01 | オペレーションパラメータ | - |
| 0x0A | 0x01 | ノード数 (n) | - |
| 0x0B | 2n | ノードコードリスト | リトルエンディアン |
| - | 0x10 | チャレンジ1A | 16バイト |
Authentication2 v2コマンドパケットのデータ構造を以下に示します。(表7.7)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | コマンドコード | 0x42 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x10 | チャレンジ2B | 16バイト |
Authentication1 v2レスポンスパケットのデータ構造を以下に示します。(表7.8)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x41 |
| 0x01 | 0x08 | IDm | - |
| 0x09 | 0x10 | チャレンジ1B | 16バイト |
| 0x19 | 0x10 | チャレンジ2A | 16バイト |
| 0x29 | 0x04 | チャレンジ3C | 4バイト |
Authentication2 v2レスポンスパケットのデータ構造を以下に示します。(表7.9)本レスポンスもIDmを含みません。トランザクション番号のみ平文で、ペイロードとMACが暗号化されています。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | レスポンスコード | 0x43 |
| 0x01 | 0x02 | トランザクション番号 (TN) | リトルエンディアン。暗号化されない |
| 0x03 | 0x10 | 暗号化ペイロード | AES-128-OFBで暗号化されている。復号後の構造は表7.10を参照 |
| 0x13 | 0x08 | 暗号化MAC | 同じOFBストリームの後段で暗号化されている |
復号後のペイロードのデータ構造を以下に示します。(表7.10)
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x08 | 発行ID (IDi) | - |
| 0x08 | 0x08 | 発行パラメータ (PMi) | - |
AES相互認証に用いる主要パラメータは以下で導出します。
16バイト定数をI0 = (01 01 00
00 80)、ノード鍵列をKnode,jとすると、

でグループ鍵Kgroupを得ます。
グループ鍵Kgroup、個別化コードKindとして

を計算します。
16バイトコンテキストブロックB(prefix,IDm)を
![B[0..1] = prefix, B[2..5] = 0, B [6..13] = IDm, B [14..15] = 0x01 0x00](card_usersmanual10x.png)
で定義し、
![α = AESH (B ([0x01,0x02],IDm ))](card_usersmanual11x.png)
![β = AESH (B ([0x02,0x02],IDm ))](card_usersmanual12x.png)
を得ます。
チャレンジ3C(4バイト)から

を作り、

で認証値を生成・検証します。
セキュアメッセージングで使うTIDはR1から導出し、
![TID = R1[2..7]](card_usersmanual15x.png)
(6バイト、先頭を0として2バイト目から7バイト目)とします。
Authentication2 v2レスポンスの復号後ペイロードは

です。
Authentication2 v2成功後、R2からセッション鍵を導出します。


Read, Write, Read v2, Write v2は、暗号化されたセキュアフレーム内部に同一形式の内部ペイロードを格納します。差分は暗号方式のみです。
| コマンド | 暗号方式 | ペイロード構造 |
|---|---|---|
| Read | DES | Read系共通(表7.12および表7.13) |
| Read v2 | AES | Read系共通(表7.12および表7.13) |
| Write | DES | Write系共通(表7.14および表7.15) |
| Write v2 | AES | Write系共通(表7.14および表7.15) |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ブロック数 (n) | 0x01 ≤ n ≤製品の最大同時読み出し可能ブロック数 |
| 0x01 | 2n〜3n | ブロックリスト | ブロックリストエレメントの2バイト形式または3バイト形式 |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ブロック数 (n) | 0x01 ≤ n ≤製品の最大同時書き込み可能ブロック数 |
| 0x01 | 2n〜3n | ブロックリスト | ブロックリストエレメントの2バイト形式または3バイト形式 |
| 可変 | 16n | ブロックデータ | 16バイト×n |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x01 | 0x01 | ステータスフラグ2 | 0x00: 正常 |
WriteコマンドでDES鍵変更を行う場合、ブロックリストエレメントのアクセスモードを0b100(鍵変更)に設定し、ブロックデータには16バイトの鍵変更パッケージを格納します。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x08 | Parameter1 | 新鍵バージョン情報を含む暗号ブロック |
| 0x08 | 0x08 | Parameter2 | 新鍵本体を含む暗号ブロック |
親鍵をKparent、旧鍵をKold、新鍵をKnew、新鍵バージョンをvとします。まず、8バイトのバージョンブロックV を

で作成し、次を計算します。



使用時は、鍵変更対象ごとに次を1組としてWriteコマンドに渡します。
複数鍵を同時に変更する場合は、ブロックリストとブロックデータの順序を一致させて並べます。失敗時はステータスフラグ2として、例えば0xAA(鍵変更失敗)や0xAB(パッケージMAC異常)が返ることがあります。
DESセッションでは、暗号化前ペイロードを

とし、任意の方式で8バイト境界へパディングしたP′にMACを付与してDES-CBC(IV=0)で暗号化します。
MACは次で計算します。
![M0 = [Len, Code, 0, 0, 0, 0, 0, 0]](card_usersmanual24x.png)

ここでBiはP′の8バイトブロック列、Len = 2 + |P′| + 8です。最終値MnをMAC(8バイト)として付与します。
応答は復号後にMAC検証し、末尾8バイトのMACを除去した後にパディングを除去します。さらにTID一致とTN単調増加を検証します。
AESセッションでは、送信データを

とします。PayloadそのものはOFBで暗号化し、MACも同じOFBストリームの後段で暗号化します。
初期ベクトルIV(16バイト)は次で構成します。
![IV [0] = 0x01, IV [1] = FrameLen, IV [2] = Code,](card_usersmanual27x.png)
![IV[3..4] = TN, IV [5..10] = TID,](card_usersmanual28x.png)
![IV[11..13] = C3C[1..3], IV[14..15] = 0](card_usersmanual29x.png)
MAC平文はAES-CMACで計算し、先頭8バイトを使用します。
![B0[0] = 0x19, B0[1..13] = IV[1..13], B0[14..15] = |P ayload|BE16](card_usersmanual30x.png)
![M AC = CMACKmac (B0 ∥ Payload)[0..7]](card_usersmanual31x.png)
OFB暗号化時、Payload長が16の倍数でない場合は次の16バイト境界までキーストリームを消費してからMACを暗号化します。
Register Issue ID, Register Area, Register Service, Change System BlockはDESセキュアコマンドとして送受信されます。暗号化前の内部ペイロード構造を以下に示します。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x08 | 発行ID | - |
| 0x08 | 0x08 | 発行パラメータ | - |
| 0x10 | 可変 | パッケージ | DESで生成された発行パッケージ |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x02 | エリアコード | リトルエンディアン |
| 0x02 | 可変 | パッケージ | DESで生成された発行パッケージ |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x02 | サービスコード | リトルエンディアン |
| 0x02 | 可変 | パッケージ | DESで生成された発行パッケージ |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x00 | なし | ペイロードなし |
レスポンス内部ペイロードのデータ構造を以下に示します。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x01 | 0x01 | ステータスフラグ2 | 0x00: 正常 |
| 0x02 | 0x02 | 残りブロック数 | ステータスフラグ1が0x00の場合のみ返送。リトルエンディアン |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x01 | 0x01 | ステータスフラグ2 | 0x00: 正常 |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x01 | 0x01 | ステータスフラグ2 | 0x00: 正常 |
| 0x02 | 0x02 | 残りブロック数 | ステータスフラグ1が0x00の場合のみ返送。リトルエンディアン |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x01 | ステータスフラグ1 | 0x00: 正常 |
| 0x01 | 0x01 | ステータスフラグ2 | 0x00: 正常 |
発行パッケージ平文(暗号化前)は16バイトで、各コマンドのフォーマットは以下のとおりです。
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x02 | サービスコード開始 | リトルエンディアン |
| 0x02 | 0x02 | サービスコード終端 | リトルエンディアン |
| 0x04 | 0x02 | サイズ | リトルエンディアン |
| 0x06 | 0x02 | 鍵バージョン | リトルエンディアン |
| 0x08 | 0x08 | エリア鍵 | - |
| オフセット | 長さ | 項目 | 値または備考 |
|---|---|---|---|
| 0x00 | 0x02 | サービスコード | リトルエンディアン |
| 0x02 | 0x02 | 予約領域 | 0x0000 |
| 0x04 | 0x02 | サイズ | リトルエンディアン |
| 0x06 | 0x02 | 鍵バージョン | リトルエンディアン |
| 0x08 | 0x08 | サービス鍵 | - |
パッケージ鍵をKpkg、平文パッケージをPとします(|P|は8の倍数、かつ0でないことが条件です)。
MAC生成鍵を

で作成します。

を計算し、最終8バイトをMACpkgとします。

を計算し、この暗号文をコマンドの「パッケージ」フィールドに格納します。
C. Herrmann et al. Proxmark3 – Iceman repo. https://github.com/RfidResearchGroup/proxmark3.
kormax. GitHub - kormax/felica-tool: Application for analyzing characteristics of FeliCa cards. 2025. url: https://github.com/kormax/felica-tool (visited on 05/28/2025).
ソニー株式会社. FeliCaカード ユーザーズマニュアル 抜粋版. Version 2.31. 2026. url: https://www.sony.co.jp/Products/felica/business/tech-support/data/card_usersmanual_2.31j.pdf (visited on 07/23/2026).
一般財団法人日本規格協会. JIS X 6319-4:2016 ICカード実装仕様―第4部:高速処理用近接型ICカード. 2016.