0

編集:

エラーはReadResource()関数内にあるようです。復号化の前に出力を印刷すると、コードはすでに切り取られています。

古いテキスト:

アプリケーションのリソース内に RC4 で暗号化された文字列を保存しています。RC4 暗号化には最大文字列サイズがあるため、大きな文字列を部分文字列に分割し、区切り記号で分割します。

今、私のアプリはリソースから読み取ることになっています。次に、区切り文字を使用してそれらを分割し、各部分文字列を復号化して、再度結合します。

文字列として「testestestestest........test」を使用してこれを試すと機能しますが、たとえば「Lorem ipsum dolor sit amet, consetetur sadipscing elitr」を使用すると、復号化中に文字列の一部が切り取られます。

これはRC4コードです:

char* rc4_crypt( char *s, size_t datalen, char *d, size_t keylen)

{
unsigned char S[SIZE];
char *data = s;
char *key = d;
int i,j,k,tmp;

  for(i = 0; i < SIZE;i++)
   S[i] = i;

  for(j = i = 0; i < SIZE;i++) {
   j = (j + S[i] + key[i%keylen]) % SIZE;
   tmp = S[i];
   S[i] = S[j];
   S[j] = tmp;   
  }

  for(i = j = k = 0; k < datalen;k++) {
   i = (i + 1) % SIZE;
   j = (j + S[i]) % SIZE;
   tmp = S[i];
   S[i] = S[j];
   S[j] = tmp;
   tmp = S[(S[i] + S[j]) % SIZE];
   data[k] ^= tmp;
  }
  return data;
}

これは、分割を処理するコードです。

std::vector<std::string> &split(const std::string &s, 
                                char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}
void print (std::string &elem)
{
    //This is because somehow 'ul' is still included 
    //as an extra element, this sorts it out
    if(elem.length() !=2) { 
        cout << elem << '\n';
        char *output = rc4_crypt((char *)elem.c_str(),
            strlen(elem.c_str()),key, strlen(key));
        cout << output << '\n';
        FinalString = FinalString + output;
    }

}

そして、これが私の主な機能です:

int main() {
  char *output;
  output = ReadResource();
  std::string stringy;
  stringy = output;
  std::vector<std::string> splitted = split(stringy,'+ul+');
  for_each (splitted.begin(), splitted.end(), print);
    cout << endl;
  cout << FinalString << '\n';
}

なぜこれが起こっているのか誰にも分かりますか?

編集:

コードを暗号化するために vb.net で使用する RC4 関数を追加しています。多分これは助けることができます:

Private Shared Function Proper_RC4(ByVal Input As Byte(), ByVal Key As Byte()) As Byte()

        Dim i, j, swap As UInteger
        Dim s As UInteger() = New UInteger(255) {}
        Dim Output As Byte() = New Byte(Input.Length - 1) {}

        For i = 0 To 255
            s(i) = i
        Next

        For i = 0 To 255
            j = (j + Key(i Mod Key.Length) + s(i)) And 255
            swap = s(i) 'Swapping of s(i) and s(j)
            s(i) = s(j)
            s(j) = swap
        Next

        i = 0 : j = 0
        For c = 0 To Output.Length - 1
            i = (i + 1) And 255
            j = (j + s(i)) And 255
            swap = s(i) 'Swapping of s(i) and s(j)
            s(i) = s(j)
            s(j) = swap
            Output(c) = Input(c) Xor s((s(i) + s(j)) And 255)
        Next

        Return Output
    End Function

EDIT2:

ReadResource() 関数は次のとおりです。

char *ReadResource() {
    TCHAR buffer[MAX_PATH];
    GetModuleFileName(NULL,buffer,sizeof(buffer));
    HMODULE ModuleH = GetModuleHandle(buffer);
    HRSRC Res = FindResource(ModuleH, L"1", L"DATA");
    HGLOBAL GlobalH = LoadResource(ModuleH,Res);
    void * ptr = LockResource(GlobalH);
    Size = SizeofResource(ModuleH,Res);
    CHAR *m_pResourceBuffer = new CHAR[Size];
    if (m_pResourceBuffer != NULL)
    {
        memcpy(m_pResourceBuffer, ptr, Size);

    }
    return m_pResourceBuffer;
}
4

2 に答える 2

2

私が正しく理解していればReadResource、暗号化されたデータを読んでいます。もしそうなら、そのデータの真ん中に簡単にゼロがある可能性があります。そのゼロは、に割り当てられたときに NULL ターミネータとして扱われますstring。したがって、最初のゼロまでしか復号化されません。最初の例では暗号化された結果がゼロにならなかった可能性がありますが、2 番目の例ではゼロになりました。

しかし、コメントで他の人がすでに指摘しているように、RC4 をバラバラにする必要はないはずです。1回の呼び出しですべてを暗号化できるはずです。そして実際には、毎回 s-box をリセットしながら同じキーで暗号化し続けるのは良くありません (安全ではありません)。結果は非常に脆弱です。これは、このウィキペディアの記事でいくつか説明されています。

それを単一のストリームとして暗号化すると、ロジックははるかに簡単に処理できます。データを (たとえば を介してReadResource) 読み取るときは、長さも取得する必要があります。その関数は長さを返す必要があります。次に、呼び出しでその長さを使用してデータを復号化します。

于 2013-02-06T00:54:57.627 に答える
1

このコードにはいくつかの問題があります。

警告: 複数文字の定数std::getlineです。1 文字の区切り記号を使用します。ulこれは、配列に表示される理由でもありますsplitted

splitted = split(stringy,'+ul+');

返された文字列を変更しますc_str()

rc4_crypt((char *)elem.c_str(), ...);

からstd::string::c_str

プログラムは、このシーケンスの文字を変更してはなりません。返されたポインターは、その値に適合する文字を格納するために文字列オブジェクトによって現在使用されている内部配列を指します。

返されたポインターは、オブジェクトを変更する他のメンバー関数への呼び出しによって無効になる場合があります。

そして最後に、カットオフの可能性が最も高い候補は

data[k] ^= tmp;

の場合data[k] == tmp、これはゼロになり、文字列はこの位置で切り捨てられます。

于 2013-02-06T01:05:52.660 に答える