S50 14443卡和15693卡 讀寫研究


雜文

 

02C3A448  2D   0804008500AABBCCDDEEFF

17B5A448  4E   0804008500AABBCCDDEEFF

A5AFA448  E6   0804008500AABBCCDDEEFF

 

文章參考

1.http://blog.sina.com.cn/s/blog_9ed067ad0100zyjx.html

2.http://www.sanlen.com/news/e7/2014-02-25/sl_news_41597.htm

3.http://blog.sina.com.cn/s/blog_9ed067ad01010i4v.html

14443

Mifare S50與Mifare S70     

Mifare S50和Mifare S70又常被稱為Mifare Standard、Mifare Classic、MF1,是遵守ISO14443A標准的卡片中應用最為廣泛、影響力最大的的一員。而Mifare S70的容量是S50的4倍,S50的容量是1K字節,S70的容量為4K字節。讀寫器對卡片的操作時序和操作命令,二者完全一致。

    Mifare S50和Mifare S70的每張卡片都有一個4字節的全球唯一序列號,卡上數據保存期為10年,可改寫10萬次,讀無限次。一般的應用中,不用考慮卡片是否會被讀壞寫壞的問題,當然暴力硬損壞除外。

    Mifare S50和Mifare S70的區別主要有兩個方面。一是讀寫器對卡片發出請求命令,二者應答返回的卡類型(ATQA)字節不同。Mifare S50的卡類型(ATQA)是0004H,Mifare S70的卡類型(ATQA)是0002H。另一個區別就是二者的容量和內存結構不同。

    Mifare S50把1K字節的容量分為16個扇區(Sector0-Sector15),每個扇區包括4個數據塊(Block0-Block3,我們也將16個扇區的64個塊按絕對地址編號為0~63),每個數據塊包含16個字節(Byte0-Byte15),64*16=1024。

如下表所示:

 扇區號

 塊號

 

  塊類型

總塊號

 扇區0

塊0

廠商代碼

廠商塊

0

 

塊1

 

數據塊

1

 

塊2

 

數據塊

2

 

塊3

密碼A   存取控制   密碼B

控制塊

3

扇區1

塊0

 

數據塊

4

 

塊1

 

數據塊

5

 

塊2

 

數據塊

6

 

塊3

密碼A   存取控制   密碼B

控制塊

7

 ...

... 

... 

 ...

 ...

扇區15 

 塊0

 

數據塊

60

 

 塊1

 

數據塊

61

 

 塊2

 

數據塊

62

 

 塊3

密碼A    存取控制   密碼B

控制塊

63

    

    Mifare S70把4K字節的容量分為40個扇區(Sector0-Sector39),其中前32個扇區(Sector0-Sector31)的結構和Mifare S50完全一樣,每個扇區包括4個數據塊(Block0-Block3),后8個扇區每個扇區包括16個數據塊(Block0-Block15)。我們也將40個扇區的256個塊按絕對地址編號為0~255),每個數據塊包含16個字節(Byte0-Byte15),256*16=4096。如下表所示:

 

扇區號

塊號

 

塊類型

總塊號

扇區0

塊0

     廠商代碼

廠商塊

0

 

塊1

 

數據塊

1

 

塊2

 

數據塊

2

 

塊3

密碼A   存取控制   密碼B

控制塊

3

扇區31

塊0

 

數據塊

124

 

塊1

 

數據塊

125

 

塊2

 

數據塊

126

 

塊3

密碼A   存取控制   密碼B

控制塊

127

扇區32

塊0

 

數據塊

128

 

塊1

 

數據塊

129

 

數據塊

 

塊14

 

數據塊

142

 

塊15

密碼A   存取控制   密碼B

控制塊

143

扇區39

塊0

 

數據塊

240

 

塊1

 

數據塊

241

 

數據塊

 

塊14

 

數據塊

254

 

塊15

密碼A   存取控制   密碼B

控制塊

255

 

    每個扇區都有一組獨立的密碼及訪問控制,放在每個扇區的最后一個Block,這個Block又被稱為區尾塊,S50是每個扇區的Block3,S70的前32個扇區也是Block3,后8個扇區是Block15。

    S50和S70的0扇區0塊(即絕對地址0塊)用於存放廠商代碼,已經固化,不可更改,卡片序列號就存放在這里。除了廠商塊和控制塊,卡片中其余的塊都是數據塊,可用於存貯數據。數據塊可作兩種應用:

    (1)用作一般的數據保存,可以進行讀、寫操作。

    (2)用作數據值,可以進行初始化值、加值、減值、讀值操作。

    數據塊和值塊有什么區別呢?無論塊中的內容是什么,你都可以把他看成普通數據,即使它是一個值塊。但是並不是任何數據都可以看成是值,因為值塊有一個比較嚴格的格式要求。值塊中值的長度為4個字節的補碼,其表示的范圍(-2147483648~2147483647),值塊的存儲格式如下:

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

addr

addr

addr

addr

VALUE

VALUE

VALUE

 

帶下划線表示取反。VALUE是值的補碼,addr是塊號(0-63).只有具有上述格式,才被認為是值塊,否則就是普通的數據塊。

    每個扇區的區尾塊為控制塊,包括了6字節密碼A、4字節存取控制、6字節密碼B。例如一張新出廠的卡片控制塊內容如下:

       A0   A1 A2 A3 A4 A5   FF 07 80 69     B0 B1 B2   B3 B4 B5

       密碼A               存取控制         密碼B 

    新卡的出廠密碼一般是密碼A為A0A1A2A3A4A5,密碼B為B0B1B2B3B4B5,或者密碼A和密碼B都是6個FF。存取控制用以設定扇區中各個塊(包括控制塊本身)的存取條件

 讀寫器與S50和S70的通訊流程如下圖所示:

S50與Mifare S70" o:button="t">
    卡片選擇三次相互認證在前面已經介紹過。其他操作如下:

    (1) (Read):讀取一個塊的內容,包括普通數據塊和值塊;

    (2) (Write):寫數據到一個塊,包括普通數據塊和值塊,值塊中寫入了非法格式的數據,值塊就變成了普通數據塊;

    (3)(Increment):對值塊進行加值,只能對值塊操作;

    (4)(Decrement):對值塊進行減值,只能對值塊操作;

   (5)中止(Halt):將卡置於睡眠工作狀態,只有使用WAKE-UP命令才能喚醒。

     事實上加值和減值操作並不是直接在Mifare的塊中進行的。這兩個命令先把Block中的值讀出來,然后進行加或減,加減后的結果暫時存放在卡上的易失性數據寄存器(RAM)中,然后再利用另一個命令傳輸(Transfer)將數據寄存器中的內容寫入塊中。與傳輸(Transfer)相對應的命令是存儲(Restore),作用是將塊中的內容存到數據寄存器中,不過這個命令很少用到。

惟一標識符說明 

    制造商塊地址是0x00,如表A-1所示。它包含IC制造商信息、惟一標識符(UID)。由於安全和系統需要,當IC制造商在生產過程中編程以后,這個塊是寫保護的,即不可改寫,符合本技術要求中對電子標簽惟一標識符的要求。

  制造商塊字節編碼(Address:0x00h)

Byte

0

1

2

3

4

5-15

Content

0   1 2 3 4 5  惟一標識符(UID)

BCC

BCC   制造商信息

    其中 為惟一標識符(UID)校驗字節,Byte4 = Byte0 ^ Byte1 ^ Byte2 ^ Byte3 

 

 

 

 

 

 

RFID讀寫器控制軟件-HID V1.0.5  使用說明(非官方)

針對 Mifare S50

  1. 測試

 

通過測試 讀取卡 知道。卡的標簽類型是Mifare S50

其數據結構:

 

  1. 密碼

1.新卡的出廠密碼一般是密碼A為A0A1A2A3A4A5,密碼B為B0B1B2B3B4B5,或者密碼A和密碼B都是6個FF。

2.出廠白卡的控制字通常是FF078069

3.每個扇區密碼獨立互不干擾。比如將0扇區密碼從6組 FF 改為 6組 AA,那么讀寫0扇區密碼就是6組 AA,而其他扇區密碼還是6組 FF;由於密碼A 是不可見 一旦忘記那你只能仰天長嘆了。(密碼數據類型:必須是十六進制數)

3.操作說明

 

4.塊號與塊數

 

 

14443卡 讀寫 Code 如下:

using RFIDRDH_NET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RFIDSystem
{
    /// <summary>
    /// s50 讀卡器
    /// </summary>
    public class Rfidrd14443
    {
        #region 自定義變量
        private static Rfidrd14443 rdh = null;
        /// <summary>
        /// 讀寫器設備句柄 大於0打開成功,小於或者等於0打開失敗
        /// </summary>
        private int handleid;
        #endregion

        #region 自定義屬性
        /// <summary>
        /// 是否打開讀寫器
        /// </summary>
        private bool isOpen = false;

        public bool IsOpen
        {
            get { return isOpen; }
            set { isOpen = value; }
        }

        //public Rfidrd14443()
        //{

        //}

        /// <summary>
        /// 打開設備 返回設備句柄
        /// </summary>
        /// <returns></returns>
        public int OpenDevice()
        {
            if (IsOpen)
            {
                return handleid;
            }
            else
            {
                handleid = RFIDRDH.RD_OpenDevice();
                if (handleid > 0)
                {
                    IsOpen = true;
                }
                return handleid;
            }
        }

        /// <summary>
        /// 關閉
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            if (RFIDRDH.RD_CloseUSB(handleid) == 0)
            {
                isOpen = false;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 創建14443卡對象
        /// </summary>
        /// <returns></returns>
        public static Rfidrd14443 GetRfidrd14443()
        {
            if (rdh == null)
            {
                rdh = new Rfidrd14443();
            }
            return rdh;
        }
        #endregion


        #region 14443卡輔助方法
        /// <summary>
        /// 寫入指定區域
        /// </summary>
        /// <param name="afi">是否包含領域標識符</param>
        /// <param name="nBlockNo">塊號</param>
        /// <param name="sbPwd">密碼</param>
        /// <param name="data">存儲數據</param>
        /// <returns></returns>
        public bool Write14443Data(string afi, int nBlockNo, StringBuilder sbPwd,StringBuilder data)
        {//寫入指定區域
            bool uafi = false;
            if (afi != null)
            {
                uafi = false;
            }
            List<RFID> rfids = GetRfidList(afi, uafi);
            if (rfids != null && rfids.Count > 0)
            {
                RFIDRDH.RD_SetUid(handleid, rfids[0].UID);//設置讀塊數據命令UID

                int r5 = RFIDRDH.RD_SelectTag(handleid);//選擇標簽
                if (r5 != 0)
                    return false;

                int r6= RFIDRDH.RD_SetAuth(handleid, 0, 0, sbPwd);//設置密碼相關參數
                if (r6 != 0)
                    return false;
                //int r7 = RFIDRDH.RD_Autnenticate(handleid, 0);//標簽認證
                //if (r7 != 0)
                //    return null;

                //StringBuilder writePwd =new StringBuilder();
                //writePwd.Append("333333333000000000000000000000000");
                int r8 = RFIDRDH.RD_WriteTagDataL(handleid, 8, data);//直接寫塊數據(為了方便管理,都存在8塊號)
                if (r8 == 0)
                    return true;
                
               
            }

            return false;
        }


        /// <summary>
        /// 讀取指定塊信息
        /// </summary>
        /// <param name="afi">是否包含領域標識符</param>
        /// <param name="nBlockNo">塊號</param>
        /// <param name="sbPwd">密碼</param>
        /// <returns></returns>
        public RFID ReadTagData(string afi, int nBlockNo, StringBuilder sbPwd)
        {
            int r100 = RFIDRDH.RD_SetBeep(handleid, 1);//為了解決蜂鳴聲重復響
            if (r100 != 0)
                return null;

            #region 獲得讀卡產品的序列號
           /* StringBuilder sbNum = new StringBuilder();
            int result =0;
            int r101 = RFIDRDH.RD_GetSerialNum(sbNum, ref result);
            if (r101 != 0)
                return null;*/
            #endregion

            bool uafi = false;
            if (afi != null)
            {
                uafi = true;
            }
            List<RFID> rfids = GetRfidList(afi, uafi);
            if (rfids != null && rfids.Count > 0)
            {
                int r4 = RFIDRDH.RD_SetUid(handleid, rfids[0].UID);//設置讀塊數據命令UID
                if (r4 != 0)
                {
                    return null;
                }
                int r5 = RFIDRDH.RD_SelectTag(handleid);//選擇標簽
                if (r5 != 0)
                    return null;

                //sbPwd.Append("ffffffffffff");
                int r6 = RFIDRDH.RD_SetAuth(handleid, 0, 0, sbPwd);//設置密碼相關參數
                if (r6 != 0)
                    return null;
                StringBuilder data = new StringBuilder();
                RFIDRDH.RD_ReadTagDataL(handleid, nBlockNo, 1, data);//塊號8,塊數1
                //if (r7 != 0)
                //    return null;

                rfids[0].blockdata = data.ToString();
                return rfids[0];
            }

            return null;
        }


        public List<RFID> GetRfidList(string afi, bool useafi)
        {
            
            List<RFID> rfidsList = new List<RFID>();
            int uafi = useafi==true ? 1 : 0;
            int r1 = RFIDRDH.RD_SetFlag(handleid, uafi, 0, 0, 1, 0, 0); //設置標志位

            if (afi != null)
            {
                int r0 = RFIDRDH.RD_SetAfi(handleid, afi);
            }
            
            if (r1 != 0)
                return null;
            int r2 = RFIDRDH.RD_SetDefTagType(handleid, "0212");//S50 Mifare 1k 
            if (r2 != 0)
                return null;

            StringBuilder sbTagPs=new StringBuilder();
            int count = 0;
            int r3 = RFIDRDH.RD_InventoryTagPs(handleid, sbTagPs, ref count);//標簽檢測

            if (sbTagPs.Length % 8 == 0)
            {//ISO14443A
                string uids = sbTagPs.ToString();

                for (int i = 0; i < uids.Length; i += 8)
                {
                    RFID rf = new RFID();
                    rf.UID = uids.Substring(i, 8);
                    rfidsList.Add(rf);
                }
                return rfidsList;
            }

            return null;
        }
        #endregion


        #region 檢測是什么卡
        /// <summary>
        /// 檢測卡
        /// </summary>
        /// <param name="afi"></param>
        /// <param name="useafi"></param>
        /// <returns></returns>
        public string CardDetection(string afi, bool useafi)
        {

            int uafi = useafi == true ? 1 : 0;
            int r1 = RFIDRDH.RD_SetFlag(handleid, uafi, 0, 0, 1, 0, 0); //設置標志位

            if (afi != null)
            {
                int r0 = RFIDRDH.RD_SetAfi(handleid, afi);
            }

            if (r1 != 0)
                return null;
            int r2 = RFIDRDH.RD_SetDefTagType(handleid, "0121");//S50 Mifare 1k 
            //int r2 = RFIDRDH.RD_SetDefTagType(handleid, "0212");
            
            if (r2 != 0)
                return null;

            StringBuilder sbTagPs = new StringBuilder();
            int count = 0;
            int r3 = RFIDRDH.RD_InventoryTagPs(handleid, sbTagPs, ref count);//標簽檢測


            if (sbTagPs.Length==16)
            {
                return "15693";
            }
            if (r3 == 7)
            {
                int s2 = RFIDRDH.RD_SetDefTagType(handleid, "0212");

                if (s2 != 0)
                    return null;

                StringBuilder sbTagPs2 = new StringBuilder();
                int s2count = 0;
                int s3 = RFIDRDH.RD_InventoryTagPs(handleid, sbTagPs2, ref s2count);//標簽檢測
                if (sbTagPs2.Length == 8)
                {//ISO14443A
                    return "14443";
                }
            }

            return "";
        }

        #endregion

    }
}

 

<Window x:Class="WpfApplicationTest._14443Window"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="_14443Window" Height="300" Width="300">
    <Grid>
        <Button Name="btn14443Read" Content="14443讀寫"  Width="100" Height="20" Click="btn14443Read_Click" Margin="96,62,96,178"></Button>
        <Button x:Name="btn14443detection"  Content="檢測卡類型"  Width="100" Height="20" Click="btn14443detection_Click" Margin="96,130,96,110"/>
    </Grid>
</Window>


 

using RFIDSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApplicationTest
{
    /// <summary>
    /// _14443Window.xaml 的交互邏輯
    /// </summary>
    public partial class _14443Window : Window
    {
        public _14443Window()
        {
            InitializeComponent();
        }

        private void btn14443Read_Click(object sender, RoutedEventArgs e)
        {//讀寫
            try
            {
                Rfidrd14443 rfidcard = Rfidrd14443.GetRfidrd14443();//實例化14443卡對象
                int mac = rfidcard.OpenDevice();//打開設備

                if (mac <= 0)
                {
                    MessageBox.Show("啟用讀卡器失敗!");
                    return;
                }
                StringBuilder sbPwd=new StringBuilder();
                sbPwd.Append("ffffffffffff");
                RFID rtag = rfidcard.ReadTagData(null,8,sbPwd);
                
                if (rtag != null)
                {
                    if (rtag.blockdata[0] == '3')
                    {
                        MessageBox.Show("此卡已激活");
                        return;
                    }
                    StringBuilder data = new StringBuilder();
                    data.Append("33333333000000000000000000000000");
                    bool wtTag = rfidcard.Write14443Data(null, 8, sbPwd, data);
                    if (wtTag)
                        MessageBox.Show("寫入成功!");
                    else
                        //卡已鎖定 不可用
                        MessageBox.Show("該卡已鎖定!");


                }
                else
                {
                    MessageBox.Show("未檢測磁卡片!");
                }
                rfidcard.Close();
                
            }
            catch(Exception ex)
            {
                MessageBox.Show("寫入異常"+ex.ToString());
            }
            
        }

        private void btn14443detection_Click(object sender, RoutedEventArgs e)
        {//檢測
            Rfidrd14443 rfidcard = Rfidrd14443.GetRfidrd14443();//實例化14443卡對象
            int mac = rfidcard.OpenDevice();//打開設備
            if (mac <= 0)
            {
                MessageBox.Show("啟用讀卡器失敗!");
                return;
            }

            string afi = string.Empty;
            bool uafi = false;
            if (afi != null)
            {
                uafi = true;
            }

           string result = rfidcard.CardDetection(null, uafi);
           if (result != "")
           {
               MessageBox.Show("這個是" + result + "");
           }
           else
           {
               MessageBox.Show("異常卡"); 
           }


        }
    }
}

 

源碼下載:密碼是我的名字,里面有介紹 C# 怎么用讀卡器  調用 15693卡  和 14443卡

有什么好的建議可以留言給我


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM