1

私は暗号化アルゴリズムに取り組んでいましたが、次のコードをより単純なものに変更する方法と、このコードを元に戻す方法を知りたいです。

typedef struct 
{
    unsigned low : 4;
    unsigned high : 4;
} nibles;

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        n->low = last;
        last = n->high;
        n->high = n->low;
    }
    ((nibles *)&data[0])->low = last;
}

data は、このコードの入力と出力です。

4

5 に答える 5

3

最終的に高ニブルを低ニブルと同じに設定するため、すべてのバイトの両方のニブルを同じものに設定しています。これはバグであり、あなたの意図はデータ内のすべてのニブルをシフトし、あるバイトから別のバイトに持ち越してローリングすることだったと思います。Id est、ABCDEF (下位から上位へのニブルの順序) は FABCDE になります。間違っていたら訂正してください。

コードは次のようになります。

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        unsigned char old_low = n->low;
        n->low = last;
        last = n->high;
        n->high = old_low;
    }
    ((nibles *)&data[0])->low = last;
}

今は大丈夫ですか?いいえ。 へのキャストは、 のアラインメントが のアラインメントより厳密でないnibbles*場合にのみ明確に定義されます。そして、それは保証されていません(ただし、小さな変更で、GCC は同じアラインメントを持つ型を生成します)。nibbleschar

個人的には、この問題は完全に避けたいと思います。これが私がそれを行う方法です:

void set_low_nibble(char& c, unsigned char nibble) {
    // assumes nibble has no bits set in the four higher bits)
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0xF0) | nibble;
}

void set_high_nibble(char& c, unsigned char nibble) {
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0x0F) | (nibble << 4);
}

unsigned char get_low_nibble(unsigned char c) {
    return c & 0x0F;
}

unsigned char get_high_nibble(unsigned char c) {
    return (c & 0xF0) >> 4;
}

static void crypt_enc(char *data, int size)
{
    char last;

    //...

    // Pass 2
    for (i = 0; i < size; ++i)
    {
        unsigned char old_low = get_low_nibble(data[i]);
        set_low_nibble(data[i], last);
        last = get_high_nibble(data[i]);
        set_high_nibble(data[i], old_low);
    }
    set_low_nibble(data[0], last);
}

逆にすると、「低」から「高」に、またはその逆になります。最初のニブルではなく、最後のニブルまでローリングします。反対方向にデータを通過します。

for (i = size-1; i >= 0; --i)
{
    unsigned char old_high = get_high_nibble(data[i]);
    set_high_nibble(data[i], last);
    last = get_low_nibble(data[i]);
    set_low_nibble(data[i], old_high);
}
set_high_nibble(data[size-1], last);

必要に応じて、一時的な へのすべての転送を取り除くことができますlast。すべての最後のニブルを保存し、別の変数を使用せずにニブルを直接シフトするだけです。

last = get_high_nibble(data[size-1]);
for (i = size-1; i > 0; --i) // the last one needs special care
{
    set_high_nibble(data[i], get_low_nibble(data[i]));
    set_low_nibble(data[i], get_high_nibble(data[i-1]));
}
set_high_nibble(data[0], get_low_nibble(data[0]));
set_low_nibble(data[0], last);
于 2011-09-22T19:26:15.030 に答える
1

各ニブルを 1 か所シフトしてから、最後のバイトの下位ニブルを取得して先頭に移動しているようです。復号化するには、逆の手順を実行するだけです ( の末尾から開始しdata、先頭に移動します)。

于 2011-09-22T18:53:47.163 に答える
0

アルゴリズムが最初のバイトを完全に削除し、残りの下半分を破棄するため、コードを逆にすることは不可能です。

forループの最初の反復で、最初のバイトの下部がゼロに設定されます。

n->low = last;

それはどこにも保存されません。それは単になくなった。

// I think this is what you were trying for
last = ((nibbles *)&data[0])->low;
for (i = 0; i < size-1; i++)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *next = (nibbles *)&data[i+1];
    n->low = n->high;
    n->high = next->low;
}
((nibbles *)&data[size-1])->high = last;

それを逆にするには:

last = ((nibbles *)&data[size-1])->high;
for (i = size-1; i > 0; i--)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *prev = (nibbles *)&data[i-1];
    n->high = n->low;
    n->low = prev->high;
}
((nibbles *)&data[0])->low = last;

...私が後方に高くそして低くならない限り。

しかしとにかく、これは暗号化の分野の近くにあります。これはせいぜい難読化です。隠すことによるセキュリティはひどいひどい慣習であり、自作の暗号化は人々を困らせます。あなたが遊んでいるなら、あなたにさらに力を与えます。しかし、実際に何かを安全にしたい場合は、すべてのバイトを愛するために、よく知られた安全な暗号化スキームを使用してください。

于 2011-09-22T19:35:36.633 に答える
0

ケビンの答えは、あなたがやろうとしていることです。しかし、あなたは初歩的なミスを犯しました。最終結果は、ニブルを回転させるのではなく、配列全体がゼロで満たされることです。

その理由を理解するために、最初{a, b, c} -> {c, a, b}に同じ方法でバイト ローテーション ( ) を実装することをお勧めします。これは、0 から配列サイズに増加するループ カウンターを使用することです。変数への転送を減らすことで、より良い結果が得られるかどうかを確認してくださいlast

その方法がわかれば、同じロジックをニブルに簡単に適用できます ( {al:ah, bl:bh, cl:ch} -> {ch:al, ah:bl, bh:cl})。ここでの私の表現は、16 進値で考えると正しくありません。16進値0xXYY:X私の表記です。バイトローテーションをどのように行ったかを考えると、ニブルを 1 つだけ保存し、ニブルを実際に に移動せずに単純に転送する方法を理解できますlast

于 2011-09-22T19:06:34.460 に答える
0

ビット フィールドを使用しているため、ニブルを移動するためのシフト スタイル メソッドが存在する可能性はほとんどありません。このシフトが重要な場合は、何らかの符号なし整数に格納することを検討することをお勧めします。そのような形で、ビット操作を効果的に行うことができます。

于 2011-09-22T18:52:47.250 に答える