Kalan's Blog

Kalan 頭像照片,在淡水拍攝,淺藍背景


本部落格支援 RSS feed(全文章內容),可點擊下方 RSS 連結或透過第三方服務設定。若技術文章裡有程式碼語法等特殊樣式,仍建議至原網站瀏覽以獲得最佳體驗。

目前主題 亮色

How to read SUICA information with CoreNFC (FeliCa)


iOS 11.0 can read and write NFC Tag through CoreNFC , but it can't read information such as IC cards. IC cards can only be read by iOS device after iOS 13.

I have been interested in NFC for a long time, I also want to read the information of Suica (Japanese transportation IC card) by myself so I can directly check the balance with my mobile phone (I know there are already serveral apps doing this, but I want to do it for study purpose)

There are relatively few Chinese, English resources on the Internet about Suica, so I spent a few days researching the FeliCa documentation and implemented it with CoreNFC.

This article will start from NFC protocol first, then talk about FeliCa, which is widely used in Japanese transportation IC cards, and finally, the implementation in swift.

While I just start learning swift, there may have some places that are not well written, feel free to pin me on twitter.

What is NFC?

NFC (Near Field Communication) is a communication protocol, also known as RFID wireless communication technology.

This agreement mainly defines as such:

  • Communication agreement: how to communicate between sender and receiver
  • Data exchange: how exchange data between sender and receiver

While it is possible to write data into card(if you have key), this article will only focus on how to read the data in FeliCa.

The Problems solved by NFC

In wireless communication we can use Bluetooth, wifi, etc. to communicate, but the biggest problem is about security and matching.

Bluetooth need to be paired before communicating with each other. It might take time to match, and this communication is more complicated.

If the reader can detect card information from 20 meters and directly request payment, there will be big problems.

Therefore, in NFC, the detection distance is usually within a few centimeters not only to ensure the security, it can also reduce the noise interference.


Felica is a IC card technology developed by Sony in 2001. Compared with NFC Type-A and Type-B, it is faster. The reason why it's so fast may because of the terrible commute traffic in Japan.

Youyou card in Taiwan is an IC card made by Mifare designed by Philips. At the same time, Mifare is also a non-contact IC card widely used around the world.

It seems that only FeliCa is widely used in Japan currently.

FeliCa is really fast. If you use public transportation in Japan, you should find that you don't have to stop your step when entering the platform

It currently widely used transportation IC cards such as Suica, ICOCA, は や か け ん, etc. all of this card use FeliCa technology.

Not only in transportation, you can also use your transportation IC card to pay in convenience store.

Data security

In NFC, some data can be read, some data cannot, and some cards need to be decrypted with the correct key to read and write data.

Although Android and iOS can now read NFC cards, if you want to modify the balance and other data, you must have the correct key.

FeliCa architecture

In FeliCa's architecture, it can be divided into two major part: private domain (プ ラ イ ベ ー ト) and common domain.

The common domain stores some information that can be read, while the private domain stores some information such as personal data or control balances, which must be encrypted and decrypted to operate.

In the common field, it can be divided into several parts:

  • System: indicates the unit of the card. Each card will have a system code (2 byte). According to law of JIS 6319-4 , this value will be between FE00 ~ AA00 . Cards like Suica are 0003(this value is important, we'll use it later)
  • Area: Contains information such as storage space, number of blocks stored by each service, and so on.
  • Service: Store data in blocks for external access. Each service will have a service code (2 bytes), such as the service code of the entry record 090f. service can be divided into random service, cyclic service, pass service
  • Block: Where data is stored, each block is 16 bytes, and the number of blocks required will vary depending on the service.

If you only want to read the information inside the card, you will encounter two parts: service and block.

Service Type

As mentioned earlier, services are divided into random, cyclic, and pass, which are mainly distinguished by data access.

  • Random Service: data that can be read and written freely, determined by the manufacturer
  • Cyclic Service: A place where you can store records like historical data.
  • Pass Service: A place to manage things like balances and deductions


There are many kinds of instructions in [FeliCa](http://www.proxmark.org/files/Documents/13.56 MHz - Felica/card_usersmanual_2.0.pdf) , which can be found in the [FeliCa document](http://www.proxmark.org/files/Documents/13.56 MHz - Felica/card_usersmanual_2.0.pdf) . To read FeliCa data, you need several command:

  • polling
  • request service
  • Read without encryption

Each command has a corresponding request pocket, which specifies what should be in the request. This part already provides corresponding functions in CoreNFC so we don't have to worry about that.

Communication process in FeliCa

  1. Capture cards with polling command.
  2. Using the Request Service command and passing in the service code list, the card will confirm whether the service code is correct or readable. If service does not exist or error, it will return0xFFFF
  3. Use the read without encryption command and pass in the service code to return the corresponding data in blocks. (Up to 16 services)
    1. This command will return status1 and status2. If both are 0, it means no problem.
    2. If it is not 0, it means there is an error. You can find out error code status in FeliCa documentation

iOS implementation

You can refer to the examples on the apple developer to find out how to read the NFC Tag, here we are just focusing on how to read FeliCaTag

To implement NFC, you must first have a physical iPhone. There is no way to read NFC in simulator.

You can use NFCTagReaderSession.isReadingAvailable to determine if NFC data is readable in your device.

5]) >> 5 & 0b1111 // get month bit let date = data[5] & 0b11111 // get date bit

let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" formatter.locale = Locale(identifier: "en_US_POSIX") return formatter.date(from: "20(year)-(month)-(date)")!

## Demo

You can see the source code on [github](https://github.com/kjj6198/nfc-reader) .

## Thought

Although the information was successfully read, some numbers are different from what I expected.

For example, the station code has not been found after searching for a long time on the Internet. I don't even know if I parsed station code in correct way.

Although it is said that the history record can get 20 blocks, some cards will fail to read because of this, the safer range is 10. (Still testing)

Looking at the records inside (my card is a regular ticket), it seems that not every entry and exit will be recorded. If you want to use cards to collect your own inbound and outbound information, I am afraid it is not so easy to use (such as visualization).

Regarding FeliCa reading, on iOS, Japanese developers have written a set of library [TRETJapanNFCReader](https://github.com/treastrain/TRETJapanNFCReader) which is quite easy to use . If you want to use it directly, you can refer to it. In addition to SUICA, he also supports quite a few types of IC cards. Even the driver's license can be read.

When I saw the CoreNFC SDK, I wanted to have a try to read FeliCa information, but there are not many Chinese resources on the Internet.

There are quite a lot of Japanese implementations. but I can just see the service code, blockList and so on without knowing the meaning of that. So it took a day to read the FeliCa documentation and try to implement by myself.

Also quite troublesome on the swift conversion of another type, such as the Data converted into UInt and so on, and got this code from the Internet, but do not really understand what he was doing XD, I can only know `UInt(bytes: Data)`the way for Conversion.

import Foundation

extension FixedWidthInteger {
    init(bytes: UInt8...) {
        self.init(bytes: bytes)

    init<T: DataProtocol>(bytes: T) {
        let count = bytes.count - 1
        self = bytes.enumerated().reduce(into: 0) { (result, item) in
            result += Self(item.element) << (8 * (count - item.offset))

It was a long journey to read all of this, isn't it? I wish you could understand how NFC works, what FeliCa is and more importantly, how to use it combine with CoreNFC in Swift!




2019 回顧

如果覺得這篇文章對你有幫助的話,可以考慮到下面的連結請我喝一杯 ☕️ 可以讓我平凡的一天變得閃閃發光 ✨

Buy me a coffee