2010-05-20 3 views
3

마그네틱 스트라이프 리더에서 데이터를 디코딩하는 응용 프로그램이 있습니다. 그러나 계산 된 LRC 체크 바이트가 카드의 것과 일치하도록 확인하는 데 문제가 있습니다. 3 개의 트랙으로 각각 3 장의 카드를 가져 오려면 아래의 알고리즘이 해당 카드의 9 개 트랙 중 4 개에서 작동한다고 추측 할 수 있습니다.경도 중복 확인에 실패했습니다.

알고리즘 I이 (C 번호)와 같은 모양을 사용하고 :

private static char GetLRC(string s, int start, int end) 
{ 
    int result = 0; 
    for (int i = start; i <= end; i++) 
    { 
     result ^= Convert.ToByte(s[i]); 
    } 
    return Convert.ToChar(result); 
} 

이 체크에 실패 3 트랙의 데이터의 일례이다. 이 카드에서 트랙 2가 일치했지만 트랙 1도 실패했습니다.

0 1 2 3 4 5 6 7 8 9 A B C D E F 
00 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 
10 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 
20 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 
30 8 8 8 9 9 9 9 9 9 9 9 9 9 0 0 0 
40 0 0 0 0 0 0 0 1 2 3 4 1 1 1 1 1 
50 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 
60 3 3 3 3 3 3 3 3 

섹터 구분 기호는 ';'입니다. '?'로 끝납니다.

이 트랙의 LRC 바이트는 0x30입니다. 불행하게도, 알고리즘은 위의 다음과 같은 계산 당 × 00의 LRC는 계산 (. 사과는 길이 나는 철저 할) : 누군가가 내 알고리즘을 수정하는 방법을 지적 할 수있는 경우

00^3b = 3b ';' 
3b^33 = 08 
08^34 = 3c 
3c^34 = 08 
08^34 = 3c 
3c^34 = 08 
08^34 = 3c 
3c^34 = 08 
08^34 = 3c 
3c^34 = 08 
08^34 = 3c 
3c^34 = 08 
08^35 = 3d 
3d^35 = 08 
08^35 = 3d 
3d^35 = 08 
08^35 = 3d 
3d^35 = 08 
08^35 = 3d 
3d^35 = 08 
08^35 = 3d 
3d^35 = 08 
08^36 = 3e 
3e^36 = 08 
08^36 = 3e 
3e^36 = 08 
08^36 = 3e 
3e^36 = 08 
08^36 = 3e 
3e^36 = 08 
08^36 = 3e 
3e^36 = 08 
08^37 = 3f 
3f^37 = 08 
08^37 = 3f 
3f^37 = 08 
08^37 = 3f 
3f^37 = 08 
08^37 = 3f 
3f^37 = 08 
08^37 = 3f 
3f^37 = 08 
08^38 = 30 
30^38 = 08 
08^38 = 30 
30^38 = 08 
08^38 = 30 
30^38 = 08 
08^38 = 30 
30^38 = 08 
08^38 = 30 
30^38 = 08 
08^39 = 31 
31^39 = 08 
08^39 = 31 
31^39 = 08 
08^39 = 31 
31^39 = 08 
08^39 = 31 
31^39 = 08 
08^39 = 31 
31^39 = 08 
08^30 = 38 
38^30 = 08 
08^30 = 38 
38^30 = 08 
08^30 = 38 
38^30 = 08 
08^30 = 38 
38^30 = 08 
08^30 = 38 
38^30 = 08 
08^31 = 39 
39^32 = 0b 
0b^33 = 38 
38^34 = 0c 
0c^31 = 3d 
3d^31 = 0c 
0c^31 = 3d 
3d^31 = 0c 
0c^31 = 3d 
3d^31 = 0c 
0c^31 = 3d 
3d^31 = 0c 
0c^31 = 3d 
3d^31 = 0c 
0c^32 = 3e 
3e^32 = 0c 
0c^32 = 3e 
3e^32 = 0c 
0c^32 = 3e 
3e^32 = 0c 
0c^32 = 3e 
3e^32 = 0c 
0c^32 = 3e 
3e^32 = 0c 
0c^33 = 3f 
3f^33 = 0c 
0c^33 = 3f 
3f^33 = 0c 
0c^33 = 3f 
3f^33 = 0c 
0c^33 = 3f 
3f^33 = 0c 
0c^33 = 3f 
3f^3f = 00 '?' 

, 나는 그것을 감사하겠습니다.

감사합니다, PaulH


편집 : '.'내가 실수로 잘못된 포함한 내 LRC 계산에 어떤 바이트 없거나있어 경우에 당신이 볼 수 있도록

(마지막이다 실제로 '\ r'). 세 트랙에서의 전체 데이터를

배의 홀수에만 나타납니다 XOR 바이트에 제안
0 1 2 3 4 5 6 7 8 9 A B C D E F 
00 % U V W X Y Z 0 1 2 3 4 5 6 7 8 
10 9 9 A B C D E F G H I J K L M N 
20 O P Q R S T U V W X Y Z 1 2 3 0 
30 1 2 3 4 5 6 7 8 9 A B C D E F G 
40 H I J K L M N O P Q R S T ? 3 ; 
50 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 9 
60 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
70 6 7 8 9 0 ? 5 ; 3 4 4 4 4 4 4 4 
80 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 
90 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 
A0 7 8 8 8 8 8 8 8 8 8 8 9 9 9 9 9 
B0 9 9 9 9 9 0 0 0 0 0 0 0 0 0 0 1 
C0 2 3 4 1 1 1 1 1 1 1 1 1 1 2 2 2 
D0 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 
E0 ? 0 . 

GetLRC() 알고리즘 재 계측 : 새로운 GetLRC()로 촬영

private static char GetLRC(string s, int start, int end) 
{ 
    int result = 0; 

    byte cur_byte = Convert.ToByte(s[start]); 

    int count = 0; 
    for (int i = start; i <= end; i++) 
    { 
     byte b = Convert.ToByte(s[i]); 
     if (cur_byte != b) 
     { 
      if (count % 2 != 0) 
      { 
       result ^= cur_byte; 
      } 
      cur_byte = b; 
      count = 0; 
     } 
     ++count; 
    } 

    if (count % 2 != 0) 
    { 
     result ^= cur_byte; 
    } 

    return Convert.ToChar(result); 
} 

계산 단계를 함수 :

00^3b = 3b ';' 
3b^33 = 08 
08^31 = 39 
39^32 = 0b 
0b^33 = 38 
38^34 = 0c 
0c^33 = 3f 
3f^3f = 00 '?' 

질문 : LRC 바이트는 카드 자체에서 가져 오거나 판독기 펌웨어로 추가합니까? (즉, 아마도 이것은 펌웨어 버그입니다)

답변

1

제안을 할 수 있습니까? 데이터를 런 길이로 저장하고 런 길이가 홀수 인 경우 xor 만 수행 한 다음 한 번만 실행합니다 (runLength & 0x01). 쓸데없는 비트 작업을 없애고 일어나는 일을 명확하게 해줍니다. 수익률 것을 이렇게 :


Run Lengths: 
(01,3b)(01,33)(10,34)(10,35)(10,36)(10,37)(10,38)(10,39)(10,30) 
(01,31)(01,32)(01,33)(01,34)(10,31)(10,32)(09,33)(1,3f) 

가 짝수/홀수 일을하는 것은 제공 :


3b^33^31^32^33^34^33^3f 
     08-->39-->0B-->38-->0C-->3F-->00 

보는 것이 훨씬 간단하고 깨끗한. 내 추측은 데이터를 보는 것, 데이터 스트림의 어딘가에 30 개가 부족하다는 것입니다. 나는

당신은 당신의 입력 매개 변수에 어떤 주장을 추가하거나 다른 검증 할 수 ... 파고 유지, 그 너머


3b^33^31^32^33^34^33^30^3F 
     08-->39-->0B-->38-->0C-->3F-->0F-->30 

것 : 30 여분이 당신에게 답을 얻을 수 있음을 추가?흥분 및/또는 널 문자열을 일으키는 시작/끝 경계를 보지는 싫어. 또한, 시작과 함께 하나의 오프 가능성이 있습니까? 포괄적/독점적 데이터 범위? 이렇게하면 트랙 3의 끝 부분에 저장된 0의 데이터 끝 부분에있는 0x030이 0x30으로 변환됩니다. 또한 데이터가 손상되었거나 손상된 LRU가있을 가능성이 있습니까? 분명히 이것은 수표가 잡으려고하는 것입니다. 아마도 뭔가 잡혔을까요?

+0

이렇게 많은 카드에서 발생하지 않는다면 실제로 무언가를 발견했다고 생각할 수 있습니다. 제안 된 알고리즘 업데이트를 만들었지 만 지적했듯이 최종 결과에는 차이가 없습니다. 알고리즘에서 사용하는 데이터 범위를 볼 수 있습니다. 전체 트랙 덤프를 추가했습니다. 그것이 틀렸다면 제게 알려주십시오. – PaulH

+0

'?'다음에 후행 0을 포함시키지 않으실 것이라는 확신이 있습니까? 귀하의 답변에 (또는 아마도 LRC가 그것을 포함하고 있습니까?) 그렇게했다면 기대하고있는 LRC를 얻을 수 있습니다. 어떤 경우에는 다른 행이 실패하는 이유와 최종 바이트가 0x00 일 경우 다른 행이 실패하는 이유를 설명 할 수 있습니다. 나는 정말로 그것을 가까이서 바라 볼 것이다. –

+2

나는''? ''* 뒤에 나오는''0' '이 비교 대상인 LRC라고 생각하고 있다고 생각합니다. – caf

1

LRC에 대한 알고리즘이 수정되었지만 LRC를 계산하기위한 데이터 형식이 잘못되었을 수 있습니다. (MSR 판독기에 따라 다름)

ANSI/ISO (Alpha 및 BCD)의 두 가지 트랙 정의 형식이 있습니다. 이진 코드는 ASCII 코드와 다릅니다.

이 경우 시작 소 센티넬은 ';'입니다. 따라서 형식은 BCD 여야합니다. (알파 시작 센티넬은 '%'이다)

LRC 사용 "진짜 트랙 데이터"(패리티 비트를 포함하지 않음) 계산, 샘플에서

Convert rule 
ASCII to BCD ->(ASCII - 0x30) 

    --Data Bits-- Parity 
    b1 b2 b3 b4 b5  Character Function 

    0 0 0 0 1  0 (0H) Data 
    1 0 0 0 0  1 (1H)  " 
    0 1 0 0 0  2 (2H)  " 
    1 1 0 0 1  3 (3H)  " 
    0 0 1 0 0  4 (4H)  " 
    1 0 1 0 1  5 (5H)  " 
    0 1 1 0 1  6 (6H)  " 
    1 1 1 0 0  7 (7H)  " 
    0 0 0 1 0  8 (8H)  " 
    1 0 0 1 1  9 (9H)  " 
    0 1 0 1 1  : (AH) Control 
    1 1 0 1 0  ; (BH) Start Sentinel 
    0 0 1 1 1  < (CH) Control 
    1 0 1 1 0  = (DH) Field Separator 
    0 1 1 1 0  > (EH) Control 
    1 1 1 1 1  ? (FH) End Sentinel 

,

  1. 변환 ASCII입니다 데이터를 BCD 형식으로 추적하십시오.
  2. BCD 데이터를 사용하여 LRC를 계산하면 결과는 0x00입니다.
  3. 그런 다음 LRC (BCD에서 ASCII)로 변환하고, 마지막으로 LRC = 0x30을 얻습니다.

P. ASCII가 알파로 변환

if(bASCII >= 0x20 && bASCII <= 0x5B) 
    { 
     return(bASCII - 0x20); 
    } 
    else if(bASCII >= 0x5C && bASCII <= 0x5F) 
    { 
     return(bASCII - 0x1F); 
    } 
관련 문제