磁気ストライプ リーダーからのデータをデコードするアプリケーションがあります。しかし、計算したLRCチェック バイトをカード上のものと一致させるのに苦労しています。それぞれ 3 つのトラックを持つ 3 枚のカードを取得した場合、以下のアルゴリズムはそれらのカードの 9 つのトラックのうちの 4 つで機能すると思います。
私が使用しているアルゴリズムは次のようになります(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 です。残念ながら、上記のアルゴリズムは、次の計算ごとに 0x00 の 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 '?'
誰かが私のアルゴリズムを修正する方法を指摘できるなら、私はそれを感謝します.
ありがとう、ポールH
編集:
LRC 計算で誤ってバイトが欠落しているかどうか、または間違ったバイトが含まれているかどうかを確認できるようにします (最後の '.' は実際には '\r' です)。3 つのトラックすべてからの完全なデータ:
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()
、奇数回出現する XOR バイトのみに提案されているように再装備されています。
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);
}
新しいGetLRC()
関数が実行する計算手順:
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 バイトはカード自体から来ているのですか、それともリーダーのファームウェアによって追加されているのですか? (つまり、これはおそらくファームウェアのバグです)