3

磁気ストライプ リーダーからのデータをデコードするアプリケーションがあります。しかし、計算した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 バイトはカード自体から来ているのですか、それともリーダーのファームウェアによって追加されているのですか? (つまり、これはおそらくファームウェアのバグです)

4

3 に答える 3

1

LRC に関するアルゴリズムは修正されていますが、LRC を計算するためのデータの形式が間違っている可能性があります。(MSR リーダーによって異なります)

ANSI/ISO で定義されたトラックのフォーマットには、Alpha と BCD の 2 つがあります。バイナリのコーディングは 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を得ました。

PS ASCII から Alpha への変換

    if(bASCII >= 0x20 && bASCII <= 0x5B)
    {
        return(bASCII - 0x20);
    }
    else if(bASCII >= 0x5C && bASCII <= 0x5F)
    {
        return(bASCII - 0x1F);
    }
于 2016-06-24T06:05:30.933 に答える
1

提案できますか?データを実行の長さとして保存し、実行の長さが奇数の場合にのみ xor を実行し、それを 1 回 (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 があるか、1 不足していると思います。その余分な 30 を追加すると、答えが得られます。


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

その先、掘り続けます…

入力パラメーターにアサートやその他の検証を追加できますか? 範囲外の開始/終了が興奮やヌル文字列を引き起こすのを見るのは嫌いです。また、スタートエンドで1本ずれる可能性はありますか?包括的/排他的なデータ範囲? これは、トラック 3 の最後に格納された 0 が 0x30 に変換されてから、データの最後に余分な 0x030 が発生する可能性があります。また、破損したデータまたは破損した LRU を持つ可能性はありますか? 明らかに、これは小切手がキャッチしようとしている種類のものです。もしかして何か引っかかった?

于 2010-05-20T20:58:53.280 に答える
0

あなたのアルゴリズムは、ウィキペディアの記事の LRC アルゴリズムと一致しません。正しいアルゴリズムを使用していますか?

于 2012-10-16T21:09:59.907 に答える