💾 Archived View for spam.works › mirrors › textfiles › hacking › mag_stripes.txt captured on 2023-11-14 at 09:55:17.
⬅️ Previous capture (2023-06-14)
-=-=-=-=-=-=-
Newsgroups: alt.2600 Path: sundog.tiac.net!europa.eng.gtefsd.com!emory!swrinde!pipex!sunic!EU.net!uunet!iat.holonet.net!clafave From: clafave@iat.holonet.net (Christopher R LaFave) Subject: Re: Hacking aTM Message-ID: <CsCvt5.Lut@iat.holonet.net> Organization: HoloNet National Internet Access System: 510-704-1058/modem References: <2v5ev9$53p@lucy.infi.net> Date: Sun, 3 Jul 1994 08:34:16 GMT Lines: 510 Magnetic stripe technology Figures and listings are at the end. Because of their widespread use, most magnetic cards adhere to well-defined standards that describe the physical and magnetic characteristics for a magnetic stripe on a plastic card. These standards outline specifications for a storage format and information interchange. This does not preclude other encoding techniques or additional data tracks for specific applications, but in most cases it makes sense to adhere to at least the basic constraints. This gives you the choice of using any commercially available magnetic encoders for your application. The technique used for encoding magnetic cards is known as "Two-Frequency, Coherent Phase Recording". Allowing for the representation of single-channel, self-clocking serial data, this methodology is generally referred to as F/2F. Self-clocking is achieved by combining data and clock bits together in a continuous, synchronous sequence. In this scheme, an intermediate flux transition signifies a one bit and the absence of an intermediate flux transition denotes a zero bit. Three data tracks defined for use on standard magnetic cards each possess different bit densities and encoded character sets. The average bit density of track 1 is 210 bits per inch (bpi). Track 1 characters are made up of six data bits and an odd parity bit, encoded with the least-significant bit first and the parity bit last, yielding a 64-character set. Taking the number of bits per inch and the number of bits per character, you can see track 1 has the capacity to hold 79 characters. Track 2 has a bit density of 75 bpi, and track 3 uses 210 bpi. Both of these tracks allow the representation of a numeric-only character set. The characters for tracks 2 and 3 are encoded using a 4-bit binary-coded decimal subset with odd parity and, like track 1, are encoded with the least significant bit first and the parity bit last. The lower density of track 2 allows up to 40 numeric characters, where 107 numerics can be squeezed onto track 3. The actual number of usable characters will be fewer since you also have the Start Sentinel, End Sentinel, and LRC characters. Though sometimes magnetic cards are moved past the read head mechanically, most applications rely on manually moving the card, either through a slotted reader or into an insertion-type reader. Typically the swipe rate is 5-20 inches per second (ips), with 50 ips being the fastest most card readers can handle. Of course, moving the card by hand will not only result in varying the absolute card velocity but, will also introduce incremental speed changes as the card accelerates and decelerates past the pickup. The F/2F scheme is very forgiving of such speed fluctuations. For all 3 tracks, the fundamental data format is similar and consists of the following elements: First, leading zero bits are encoded to indicate the presence of an encoded magnetic card and provide synchronization pulses to the read head electronics and ultimately to the controller. Next, the Start Sentinel character is encoded which indicates the start of the actual data. The coded data follows. Next, the End Sentinel terminates the data portion of the card and followed by an LRC byte (used for error detection). The LRC is essentially a horizontal parity calculated by an exclusive-OR of all the data bits from the Start Sentinel to the End Sentinel (inclusive). Finally, trailing zeros follow the LRC and fill out the remainder of the card. ANATOMY OF A MAGNETIC CARD The magnetic tracks have inherent characteristics based on details such as code set and bit and character densities. International organizations such as Mastercard and VISA impose additional constraits for their participating members and standards exist for bank debit cards and ATM cards as well. These rules specify the exact content and format of each data field in aech track as well as the intended uses for the tracks. Naturally, for nonfinancial uses, it is not necessary to comply with these standards. For dedicated uses such as access control, people tracking, and material tracking, adhering to the minimal standards is adequate. The most-often-used track is track 2, although it offers the lowest inform- ation density of the three. It contains all the information that is normally used for credit card transactions. When a customer name is required, track 1 must be used since it is the only track that permits alphanumeric data. Track 3 is specified for numeric-only data, but is unique. It is intended for change- able data and consequently may not only be read but may be rewritten by the transaction-handling equipment. A multitude of data fileds are contained in these various tracks. Figure 1 shows a brief run-down of what is generally placed on tracks 1 and 2. REAL CARD READERS The recovery of magnetically encoded F/2F data can be accomplished directly with the use of just about any microcontroller. There are no particular difficulties in deciphering the raw F/2F data stream and many early magnetic read heads contained nothing more than signal amplifiers and line drivers. These are now artifacts since all modern magnetic read heads contain integ- rated F/2F bit recovery circuitry and interface with the host controller in a standard fashion using three wires: CARD PRESENT, CLOCK, and DATA. The read heads usually rely on a single chip to perform the linear signal conditioning, sychronization, and recovery of individual bits from the data stream. The Mag- Tek 21006505 IC is representative of this type of data recovery circuit and its functionality is depicted in figure 2. Linear conditioning consists of raising the level of the magnetic pickup's input signal, rejecting common-mode noise, conditioning and detecting the signal, and finally providing a digital output for susequent processing. The enable/disable counters provide initialization for the recovery section. The recovery section locks onto the data rate and recovers the individual data bits from the data stream. The oscillator section provides the clocks for the recov- ery section and for the enable/disable timers. Card present goes low after 8 or 9 flux reversals are seen from the magnetic pickup and will return high about 50 ms after the last flux reversal. The strobe line signals that data is valid and is active low. The data pin indicates a one bit when it is low. Raw F/2F data can also be picked directly off the chip. The data rate for a high-density track scanned at 50 ips comes to 10500 bits per second (bps). This results in a transfer rate of 1500 characters per second for the 7-bit elements used on track 1, and 2100 characters per second using the 5-bit elements of track 3. I either case, this translates to a new bit arriving at the controller just under every 100 us (microsecond). Even the most anemic controller should be able to keep up. With resonably good coding techni- ques, there should be no problem handling the entire data sampling phase on an interrupt-driven basis. The low-density (track 2) data flows at a more pedes- trian 3750 bps, yielding 750 5-bit characters per second, or a new bit every 266 us. Since most dual-track read heads provide track 1 and track 2 data, this indicates that handling both tracks simultaneously is feasible under interrupt control. Keep in mind that 50 ips is a rather fast scan rate; 20-30 ips is probably a more realistic limit. MAGNETIC BIT STORMS When approaching a problem such as decoding magnetic cards, it pays to spend some time looking at the overall picture before starting to write the code. At first glance, it would seem that organizing the data into the prevailing element size during the sampling interval would make decoding easier. This could be easily done by ignoring all the leading zeros, with actual data storage comm- encing with the first one bit. Of course, this approach assumes you're getting good data. The fact that the data recovery is handled using well-proven hard- ware makes this assumption valid. If all you need to do is decode the card in a forward direction, then going about things as I just described makes sense and reduces the coding effort to a trivial exercise. If you have to support reverse decoding then this is not the optimal solution. Having considered the tradeoffs of being able to decode a magnetic card in both forward and reverse directions, I decided to structure the program to work equally well in either direction at the cost of a slight increase in initial complexity. The first step in decoding is to acquire the serial bit stream. This can be done using a dedicated sample loop or, with a little more work, using interrupt processing. Since the idea is the same regardless of the details, I decided to use a sample loop in my demonstration program (listing 1). The code simply records the incoming data stream and deposits the data in a sample buffer a byte at a time. Sampling begins when Card Present returns idle. Any incomplete byte that has been partially assembled at the time when sampling terminates is simply discarded. The abundance of leading and trailing zeros allows losing some bits at either end causing any problems. Once the sampling interval completes, control is transferred to the decoding algorithm. Presented in listing 2, the track-1 decode algorithm consists of nothing more than some initialization and the essence of the decode logic. Limiting the gyrations contained in the main body of this routine not only makes the logic easy to follow, but permits the same code to handle the decoding in either a forward or reverse direction. The initial entry point assumes a forward decode attempt and sets up the necessary flags, pointers, and counters before jumping into the main initial- ization code. After initialization, the sample buffer is scanned for the first one bit, at which time a 7-bit element is assembled. If the parity is correct and the character code checks out to be a Start Sentinel, the code proceeds and starts pulling successive data elements from the sample buffer. If the data element is not an End Sentinel, the character is translated to ASCII and stored in the decode buffer. Should an End Sentinel be detected, the program extracts the next character, which is assumed to be the LRC byte, and finally checks the calculated LRC for a value of zero. The checks and balances included in the execution of this loop include things such as parity, a cumulative LRC, and checking to make sure I haven't run out of samples. If everything checks out, the program terminates and returns with the DPTR pointing to the decoded data buffer and the character count contained in ACC. Should a decode failure occur, a test is performed on the direction flag and if this is an attempt at a forward decode, the routine jumps to the reverse initialization entry point. The reverse entry is similar to the forward decode entry but sets up the sample pointer to the end of the sample buffer and sets the direction flag to indicate a reverse operation. The routines contained in the intermediate layer are shown in listing 3. The meaning and operation of these routines should be apparent. The key routine in this section is GET_BIT, which picks off the next bit from the sample buffer, essentially restoring the sequential nature of the initial magnetic bit stream. FIND_START is used to synchronize with the first one bit. GET_CHAR first checks to make sure it hasn't run out of samples, then assembles the next 7-bit data element while doing a parity test and LRC calculation. Any problems encountered here are sent back to the caller and are handled there. STORE_CHAR translates and deposits the data character into its respective location in the decoded-data buffer and increments the character counter. Listing 4 shows the low-level code. These routines perform the most rudiment- ary functions and operate in accordance with the direction flag. INDEX_PTR either increments or decrements the sample pointer, POSITION_BIT likewise does either a right or left shift and LOCATE_BIT returns the state of the least- or most- significant bit of the accumulator. GO AHEAD, TAKE A SWIPE Let me touch on a few additional points that may not be immediately apparent before signing off. Storing the sampled data in a continuous stream makes the sample routine work equally well with the various bit configurations used for the different recording tracks. This would not be easily attained if you tried to generate a particular element format during sample time. Furthermore, if you look at the differences between the encoded character sets and the bit formats for the different tracks, you will find that they differ in only a few areas. With a few minor changes, such as the defined Start Sentinel, number of bits per element, and character translation method, the decode routine I've shown could easily be coerced to handle the decoding of any of the standard magnetic tracks. As a matter of fact, by recoding and redefining the hard-coded constants as variables, these could be set up for the particular data track at execution time before invoking the decode function. Doing so would not only save program memory, but would also allow you to use a routine you were comfortable with.