2

WEPにFMS 攻撃を実装しようとしています。この攻撃は、RC4 sbox の一部が変更されない可能性を利用して、「既知の」sbox 状態を作成し、キーをリバース エンジニアリングすることを理解しています。多くのサンプルでは、​​正しいキー オクテットがノイズよりも頻繁に表示されるはずです。

頻度カウントに追加する値は次のとおりです。

ここに画像の説明を入力

どこで(私は思う;表記は適切に定義されていません)

  • B は 0 から始まります
  • P.out は、出力されたキーストリーム バイトです。
  • SはSボックスです
  • j は、RC4 キー スケジューリング アルゴリズムで使用される「ポインタ」です。

私のコードでは、600 万個のデータ パケットを生成しています。一定のルート キーと一定の平文を使用して一定のヘッダーをシミュレートしRC4(IV + root_key).encrypt(plaintext)、最初の 256 オクテットを破棄せずに で暗号化します)。(IV, encrypted_data)ペアはget_key関数を介して実行されます。

uint8_t RC4_ksa(const std::string & k, std::array <uint8_t, 256> & s, const uint16_t octets = 256){
    for(uint16_t i = 0; i < 256; i++){
        s[i] = i;
    }

    uint8_t j = 0;
    for(uint16_t i = 0; i < octets; i++){
        j = (j + s[i] + k[i % k.size()]);
        std::swap(s[i], s[j]);
    }

    return j;
}

std::string get_key(const uint8_t keylen, const std::vector <std::pair <std::string, std::string> > & captured){
    std::string rkey = "";               // root key to build
    const std::string & pt = header;     // "plaintext" with constant header

    // recreate root key one octet at a time
    for(uint8_t i = 3; i < keylen; i++){
        // vote counter for current octet
        std::array <unsigned int, 256> votes;
        votes.fill(0);

        uint8_t most = 0;                // most probable index/octet value

        // get vote from each "captured" ciphertext
        for(std::pair <std::string, std::string> const & c : captured){
            const std::string & IV = c.first;

            // IV should be of form (i = root key index + 3, 255, some value)
            if ((static_cast<uint8_t> (IV[0]) != i) ||
                (static_cast<uint8_t> (IV[1]) != 0xff)){
                continue; // skip this data
            }

            const std::string & ct = c.second;
            const std::string key = IV + rkey;

            // find current packet's vote
            std::array <uint8_t, 256> sbox;           // SBox after simulating; fill with RC4_ksa
            uint8_t j = RC4_ksa(key, sbox, i);        // simulate using key in KSA, up to known octets only

            uint8_t keybytestream = pt[i - 3] ^ ct[i - 3];

            // S^-1[keybytestream]
            uint16_t sinv;
            for(sinv = 0; sinv < 256; sinv++){
                if (sbox[sinv] == keybytestream){
                    break;
                }
            }

            // get mapping
            uint8_t ki = sinv - j - sbox[i];

            // add to tally and keep track of which tally is highest
            votes[ki]++;
            if (votes[ki] > votes[most]){
                most = ki;
            }
        }

        // select highest voted value as next key octet
        rkey += std::string(1, most);
    }

    return rkey;
}

完全に間違ったキーを取得しています。エラーはおそらく 1 回限りのエラーか、そのようなばかげたことだと思いますが、2 人にこれを見てもらうように依頼しましたが、どちらも何が問題なのか理解できませんでした。

露骨に間違っていることはありますか?そうでない場合、それほど明らかに間違っていないのは何ですか?

4

0 に答える 0