RFID Mifare Card 如何進行資料存取 -1

RFID Mifare Card 如何進行資料存取 -1

這是我之前的一個項目,目前這項目已經結束了,這項目是一套實體的遊戲,在要執行這個遊戲的時候,會要刷取一個會員卡,且為了要防止網路斷線客人就無法玩的問題,因此我們後來決定將客人的客戶編號、客戶名稱、儲值金額與一組申請金鑰的時間,這些資料除了存放到 Server 上之外,我們也會將這資料存放到客戶的會員卡中。

當然存資料進去之前除了卡片本身有設定密碼之外,存進去的資料我們也會使用 RSA 加密,加入那個申請金鑰的時間就是擔心就算是使用 RSA 加密,也會有被破解的一天,尤其是像目前已經出現量子電腦,這個 RSA 加密,在未來能夠被快速破解的日子離現在應該是不遠了,因此我們如果為了要防止這狀況,所以在每張會員卡中還加入了這個申請金鑰的時間,請這個時間會到微秒,這是認證的一個很重要的一環,如果使用者手上的時間與 Server 上紀錄的時間不同時,就會立即視為這張卡片失效,因此就算駭客能破解掉我們的 RSA 加密,他最多是破解掉這張卡片的數據,無法仿造其他卡片的資料,也止血於這張會員卡(好像扯遠了)。

我們當時在選擇會員卡的時候,最後我們是選擇了 Mifare 的卡片,在 Mifare Card 可能大家很陌生,他有另外一個叫法叫做 NFC 卡,這個名稱大家可能就很有感覺了,因為目前手機上應該都有這個功能了,NFC 跟 RFID 高頻的頻率都是一樣的,所以基本上我用 RFID 或是使用 NFC 都是可以讀取 Mifare 的卡片,NFC 跟 RFID 高頻的頻率是 13.56 MHz,差別在於 RFID 高頻感應距離大約有 5 公分,最長有遇過可以到 12 公分的感應距離 (如果要在更長的感應距離,必須要重新去跟 NCC 申請安規),而 NFC 的感應距離只有 1~3 公分左右,所以有一陣子 NFC 我們又稱他為「碰一下」。

在 Mifare 的卡片中有明確的定義了卡片的容量大小,一般有分為 1K 跟 4K 的容量,當然還有更小的例如錢扣,只是沒有用過,他們的差別在於他可以存進去的資料內容,我們當時選定 Mifare 卡片是 1K 的,1K 跟 4K 的容量差別在於:

  • 1K:16 個儲存區 (Sector)
  • 4K:64 個儲存區

每個儲存區會有 4 個儲存塊 (Block),每個儲存塊可以存放 16 個 Byte,因此 16 個儲存區 * 4 個儲存塊 * 16 Byte = 1024 Byte;必須要特別注意一點,這些儲存塊中並不是每一塊資料都能被寫入哦,詳細請參考圖1. Mifare 儲存區示意圖

  • 第1個儲存區 (Sector),是存放 CSN (Card-Select Number) ,這個儲存區塊是只能讀取不能寫入
    • 第 1~4 Byte 為 UID。
    • 第 5 Byte 為位元計數檢查碼(Bit Count Check)
    • 其餘的存放卡片製造商的資料
  • 第2~16個儲存區(Sector),才是存放 Data 的資料區,所以其實只有 15 個 Sector 可以存放資料
  • 每個 Sector 有 4 個 Block,最後一個 Block 是存放 2 組金鑰(KeyA、KeyB),預設全為 0 或是全為「F」,正常來說是全為 F,因為 0 是代表空,但是真的有遇過預設是全為 0 的卡片
  • 依此類推,真實可以存放的資料變成了 15 個 Sector * 3 個 Block * 16 Byte = 720 Byte,因此這部分必須要特別小心

圖1. Mifare 儲存區示意圖

另外有一件事情要特別注意的是,這些資料要存入或是要讀取出來的時候,都要被轉換成 16 進位的資料才能寫入,因此讀取出來的資料也是 16 進位的資料,也因為空間不大,因此在存放資料時必須要特別注意你要存放的內容格式。

你的一筆資料可以存放到他一個 Block,你也可以把資料串接起來用文字的方式串接後再存放,關鍵是你的要存的資料大小會不會超過,意思是說,我可以將資料這樣分配:

  • 你可以分散式儲存
    • Sector 2 / Block 0:存放會員編號 (10 碼)
    • Sector 2 / Block 1:存放會員名稱 (10 碼)
    • Sector 2 / Block 2:存放會員儲值金 (4 碼,INT32 為 8 個 Byte)
    • Sector 3 / Block 0:存放申請金鑰日期(共 10 碼 yyyy/MM/dd)
    • Sector 3 / Block 1:存放申請金鑰時間(共 14 碼 HH:mm:ss)
    • Sector 3 / Block 2:存放申請金鑰微秒(共 5 碼 fffff)
  • 你也可以集中式儲存
    • 會員編號@會員名稱@儲值金@申請金鑰時間(yyyy/MM/dd HH:mm:ss.fffff)
    • 依據上面計算大約需要60個字
  • Json 的儲存放式
    • {"A":"會員編號", "B":"會員名稱", "C": "儲值金"....}
    • 必須要特別注意資料大小的問題

以上兩種方式都有人在用,我個人的建議是,如果你的資料不敏感,你可以直接用第一種分散式儲存方式,再加上 Mifare Card 本身的加密方式便可。但是如果當你的資料的敏感度是很高的,那我個人不建式採用第一種方式,會建議採用第二種或是第三種方式,但是如果是第三種方式就要特別注意 Json 的長度,畢竟它會多出很多的字節出來,而採用這一類集中式的儲存方式時,你可以再將資料進行 RSA 加密,經過 RSA 加密後資料的長度會在 300 ~ 400 個字節左右,再去拆解成每 16 個字節存在一個 Bolck,最終以400個字節來算,我的資料會被拆解分別放到 25 個 Block 中。

資料存放的方式可以有很多種方式儲存,反正最終你要存放的時候必須要轉換成 16 進位便可,因此資料儲存大置放會分成下列這幾種:

  • ASCII 文字:
    • 就是英數字幾個字就算幾個 Byte 很好計算
    • 簡單說就是要將你的資料先轉換成 ASCII,再轉換成 Byte,在轉換成 16 進位儲存便可
  • Bool:
    • 0 / 1,一個布林值只佔一個 Bit
    • 也就是一個 Byte 你可以存放 8 個 Bit 資料,一個欄位有 16 個 Byte,你可以存放128個布林值
    • 所以你可以將 128 個布林值轉換成一個 16 進位的資料來儲存
  • Int 8:
    • 0~255的數字,其實 0~255 的數字你可以直接將它當成 ASCII 去儲存,因為是一樣的內容
  • UInt16 / Int16:
    • 數字 0~65535 或是 -32767~32766,共佔了 4 個 Byte
    • 轉換也是先將 UInt16 / Int16 轉換成 Byte 再轉換成 16 進位儲存便可
  • UInt32 / Int32:
    • 數字 0~4,294,967,295‬ 或是 -2,147,483,648~2,147,483,647,共佔了‬ 8 個 Byte
  • UInt64 / Int64:
    • 數字 0~18,446,744,073,709,551,615或者 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807,剛剛好佔了‬ 16 個 Byte
  • BCD:
    • BCD 的意思就是將16進位的符號去除掉 A~F 只取 0~9的值,作為是資料的內容基本上與數字一樣,一般比較少人會去使用 BCD,但是在高科技產業的機台會比較常見。
    • 因為不需要再額外做轉換,獲取到資料後便可以立即處理
  • UniCode:
    • 中文字 / 韓語 / 日語 ... 等可以採用 Uni-Code的資料
    • Uni-Code的資料一個字會佔掉 2 個 Byte 這點要特別注意
    • 必須要先將中文字已 Uni-code 的編碼轉換成 Byte,再將 Byte 轉換成 16 進位的資料便可

上述的幾種資料型態都是可以將資料存入到 Mifare Card 卡,就看項目的需求與類型是要用哪一種方式去進行儲存,只要經過資料規劃,便可以很方便地去使用 Mifare Card 卡,其實你可以將 Mifare Card 卡當作是一個記事本來看,它說穿了就是一個文字儲存器,只是這個儲存器從虛擬的檔案,變成是一個實體,可以被人帶在身上的物品,並且透由特殊的工具,如 RFID / NFC ...等只要是射頻為 13.56 MHz 的頻率便可以將資料讀取出來或是寫入進去。

在 Mifare Card 中,其實是有一個小晶片,這個小晶片當中會外接天線,你將 Mifare Card 卡割開之後便可以看到天線了,RFID Reader 當發出讀取命令的時候,會去將數據透由頻率射出的方式向四處散射,而此時當 Mifare Card 這時候剛剛好接近讀卡機時,這時候的卡片天線因為接收到射頻,而射頻中會帶有微量的電壓 (大約2福特左右),這個微量的電壓就可以驅動 Mifare Card 上的小晶片,而晶片這時候會在通訊訊號中,將參雜在其中的資料或是指令獲取出來,進行判斷指令識別、驗證與寫入或讀取數據,並在透由反波將數據夾雜在訊號中反送回去,這便是整個 Mifare Card 讀取的過程。

這邊有一個重點,就是因為它是透過天線去接收訊號,並透過訊號中的微電壓去驅動,因此如果在卡片的前後帶有載體,且載體是具有帶電系數的載體(如鐵、碳纖維... 等)時,這種狀況下很有可能會導致他無法運作,或者是當如果你將一片以上的卡片放在一起去感應時,可能會無法順利地讀取到你要的數據,因為你的反送書據可能會驅動第二張卡片,而第二張卡片會將反送資料當作指令在判讀,進而的視為這是無效指令,因此當你有一片以上的卡片要讀取時,一定要分開讀取,不要疊加在一起讀取。