21

文字列を暗号化する既存のc++コードがあります。今、私はで同じ暗号化を行いました。 暗号化された文字列の一部が一致しています。1文字または2文字が一致しないものもあります。

なぜそれが起こっているのか理解できません。両方のコードが同じキー、ソルト、暗号化されるiv文字列を持つライブラリを呼び出すまで、両方のコードをデバッグモードで実行しました。

1バイトのパディングを変更しても、暗号化された文字列が大幅に変更されることはわかっています。しかし、ここでは1つか2つの文字が変化しているのを見ています。これがサンプルです(星の間の太字は不一致の部分です)

java:

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ * Pw * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0F

C ++:

U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQ * jQ * yV15HEoyECBeAZ6MTeN + ZYHRitKanY5jiRU2J0KP0F

AES暗号化を使用しています。プロバイダーはSunJCEバージョン1.6です。プロバイダーをバウンシーキャッスルに変更してみました。それでも結果は同じです。

もう1つのサンプルを追加しました:

C ++:

U2FsdGVkX18xMjM0NTY3O * I * / BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK + / 94dKLPXaZDDlWlA3gdUNyh / Fxv * oF * STgl3QgpS0XU =

java:

U2FsdGVkX18xMjM0NTY3O * D * / BMu11HkHgnkx + dLPDU1lbfRwb + aCRrwkk7e9dy ++ MK + / 94dKLPXaZDDlWlA3gdUNyh / Fxv * j9 * STgl3QgpS0XU =

アップデート:

コメントによると、base64暗号化が原因だと思います。両方の場所でLatin-1文字セットを使用しています。私がチェックできる他のもの

4

2 に答える 2

7

はぁ!!

問題は、データを暗号化し、暗号化されたデータをバイト文字列として受信した後、Base-64変換を介して送信する前に、データに対して何らかの文字変換を実行していることです。

文字列「ABC_D_EFG」と「ABC_G_EFG 」を暗号化すると、暗号化された出力は4文字目から最後まで完全に異なることに注意してください。言い換えると、Base-64の出力は次のようになります(作成された値を使用)。

U2FsdGVkX18xMj

U2FsdGXt91mJpz

上記の例では、2つの分離されたBase-64文字(1バイト)のみが混乱しているという事実は、暗号化後に破損が発生していることをほぼ証明しています。

暗号化プロセスの出力は、文字シーケンスではなく、バイトシーケンスです。観察された破損は、バイトを文字として誤って解釈し、Base-64コンバーターにフィードする前にコードページ変換を実行しようとしたことと一致しています。暗号化機能からの出力は、変換せずにBase-64コンバーターに直接供給する必要があります。

「両方の場所でLatin-1文字セット」を使用していると言います。これは、実行してはならない変換を実行していることを明確に示しています。文字セットをいじくり回す必要はありません。

于 2012-06-20T21:11:10.293 に答える
2

最初のコード:

import javax.xml.bind.DatatypeConverter;

..。

public static void main(String[] args) {
    String s1j = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQPwyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    String s1c = "U2FsdGVkX18xMjM0NTY3OGEL9nxFlHrWvodMqar82NT53krNkqat0rrgeV5FAJFs1vBsZIJPZ08DJVrQjQyV15HEoyECBeAZ6MTeN+ZYHRitKanY5jiRU2J0KP0Fzola";
    byte[] bytesj = DatatypeConverter.parseBase64Binary(s1j);
    byte[] bytesc = DatatypeConverter.parseBase64Binary(s1c);
    int nmax = Math.max(bytesj.length, bytesc.length);
    int nmin = Math.min(bytesj.length, bytesc.length);
    for (int i = 0; i < nmax; ++i) {
        if (i >= nmin) {
            boolean isj = i < bytesj.length;
            byte b = isj? bytesj[i] : bytesc[i];
            System.out.printf("%s [%d] %x%n", (isj? "J" : "C++"), i, (int)b & 0xFF);
        } else {
            byte bj = bytesj[i];
            byte bc = bytesc[i];
            if (bj != bc) {
                System.out.printf("[%d] J %x != C++ %x%n", i, (int)bj & 0xFF, (int)bc & 0xFF);
            }
        }
    }
}

これは

[60] J 3f != C++ 8d

これで、0x3fが疑問符のコードになります。

エラーは、0x80-0xBFがLatin-1であり、正式ISO-8859-1には制御文字であるということです。Windows Latin-1は、公式Windows-1252には、これらのコードを他の文字に使用します。

したがって、Javaでは「Windows-1252」または「Cp1252」(コードページ)を使用する必要があります。


ぶっきらぼう

暗号化では、0x80 .. 0xBFの範囲の元のバイトは、Windows-1252からbyte []ではなくISO-8859-1に変換されたため、疑問符に置き換えられました。

于 2012-06-20T20:12:28.533 に答える