.net - Determine Facility Code and Card Number from ATR in C# -


i have following card reader hid omnikey 5325. have contact-less card named proximity.

the number written on card 133593 42101044091-3.

by reading card, following atr hex: 3b050002f10673

using folowing applications have managed see following information.

pacs probe hello prox

i need extract facility code , code number in order identify card.

i have managed find following code, missing few pieces:

/// <summary>     /// extract data item wiegand raw data. data item card      /// number or facility code.     /// </summary>     /// <param name="format"></param>     /// <param name="identifier"></param>     /// <returns></returns>     public int getdata(int format, int identifier)     {         int byteoffset = 0;         if (m_rawwieganddata == null)         {             throw new exception("no raw wiegand data available");         }         //self-test         byte[] testdata_h10301 = {0x02,0x02,0x00,0x7a}; //cn=61, fc=1         byteoffset = 0;         int bitoffset = 1; // starting count right         int numberofbits = 16;         int cn_h10301 = cardhex.frombytearray(testdata_h10301, byteoffset, bitoffset, numberofbits);         if (cn_h10301 != 61) throw new exception("cardhex::fromarray(): system integrity error.");            if (format == pacsdataformat.hid_h10301 && identifier == pacsdataidentifier.card_number) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 1, 16);         //if (format == pacsdataformat.hid_h10301 && identifier == pacsdataidentifier.card_number) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 15, 16); //assuming 4-byte input, 6 leading 0 bits         if (format == pacsdataformat.hid_h10301 && identifier == pacsdataidentifier.facility_code) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 17, 8);         //if (format == pacsdataformat.hid_h10301 && identifier == pacsdataidentifier.facility_code) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 1, 8);         if (format == pacsdataformat.hid_h10302 && identifier == pacsdataidentifier.card_number) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 1, 24);         if (format == pacsdataformat.hid_h10304 && identifier == pacsdataidentifier.card_number) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 1, 19);         if (format == pacsdataformat.hid_h10304 && identifier == pacsdataidentifier.facility_code) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 20, 16);         if (format == pacsdataformat.hid_h10320 && identifier == pacsdataidentifier.card_number)         {             long result = 0;             // convert bcd encoded raw wiegand skipping least significant nibble             //todo: create new method in cardhex convert bcd int              (int k = 0; k < m_rawwieganddata.length; k++)             {                 int high = (int)(m_rawwieganddata[k] >> 4);                 int low = (int)(m_rawwieganddata[k] & 0x0f);                 result *= 10;                 result += high;                 if (k < m_rawwieganddata.length - 1) // skip last digit i.e. nibble                 {                     result *= 10;                     result += low;                 }             }             return (int)result;              }          // h10320 cn=12345678 dec=                      101111000110000101001110         //        atr_hist(5125)=100100011010001010110011110001100           // h10320 cn=1 dec =     1         //        atr_hist(5125)=10101          // h10320 cn=99999999 dec =       101111101011110000011111111      1         //        atr_hist(5125)=100110011001100110011001100110010100           if (format == pacsdataformat.hid_corp1000 && identifier == pacsdataidentifier.card_number) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 1, 20);         if (format == pacsdataformat.hid_corp1000 && identifier == pacsdataidentifier.facility_code) return cardhex.frombytearray(m_rawwieganddata, byteoffset, 21, 12);         return 0;     } public static class pacsdataformat     {         public const int unknown      = 0;         public const int hid_h10301   = 1; // 26-bit, fac,cn         public const int hid_h10302   = 2; // 37-bit, cn         public const int hid_h10304   = 3;         public const int hid_h10320   = 4; // 32-bit, clock-and-data card; cn bcd encoded         public const int hid_corp1000 = 5; // 35-bit, cic,cn          public const int indala_flexpass26 = 6; // 26-bit, fac,cn     }      public static class pacsdataidentifier     {         public const int unknown       = 0;         public const int weigand_raw   = 1; // raw weigand data         public const int card_number   = 2; // card number printed on card         public const int facility_code = 3; // facility code         public const int cic           = 4; // cic     } 

i can't figure out frombytearray function. have found description here on page 69: http://www.intraproc.com/downloads/fargo/hdp5000%20old/omnikey%20cardman%205121/manuals/ok_contactless_developer_guide_an_en.pdf

edit: solution have created frombytearray function goes code @chris haas

    /// call example: frombytearray(atrbytearray, byteoffset: 0, int bitoffset: 1, int numberofbits: 16)     /// call example: frombytearray(atrbytearray, byteoffset: 0, int bitoffset: 17, int numberofbits: 8)     public static long frombytearray(byte[] atrbytearray, int byteoffset, int bitoffset, int numberofbits)     {         var hexstring = bytearraytostring(atrbytearray);          var start_number = int64.parse( hexstring, numberstyles.hexnumber );          int64 a_26_only = start_number & 0x3ffffff; //26 bits, 11 1111 1111 1111 1111 1111 1111                         int64 result = (a_26_only >> bitoffset) & (long)(math.pow(2,numberofbits)-1);                 return result;     }      public static string bytearraytostring(byte[] ba)     {       stringbuilder hex = new stringbuilder(ba.length * 2);       foreach (byte b in ba)         hex.appendformat("{0:x2}", b);       return hex.tostring();     } 

and usage:

        byte[] atrbytearray = new byte[] {59, 5, 0, 2 , 241, 6, 115};         var cardnumber = frombytearray(atrbytearray, 0, 1, 16);         var facilitycode = frombytearray(atrbytearray, 0, 17, 8);          console.writeline(string.format("card number is: {0} , facility code is: {1}", cardnumber, facilitycode)); 

i'm not sure full-length number 3b050002f10673 but, per spec, you're interested in right-most 26 bits of it.

int64 start = 0x3b050002f10673;  int64 a_26_only = start & 0x3ffffff; //26 bits, 11 1111 1111 1111 1111 1111 1111 

then, per spec, right-most bit parity bit, after checking can discard it:

int64 a_without_parity = a_26_only >> 1; 

finally, card number right-most 16 bits:

int64 card_number = a_without_parity & 0xffff; 

and facility code next 8 bits:

int64 facility_code = (a_without_parity >> 16 ) & 0xff; 

Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -