2

整数を文字列に変換してから、XOR暗号化で文字列を暗号化しようとしています。しかし、Strinを再度復号化すると、暗号化の前に入力した文字列という別の答えが返されます。何が間違っているのかわかりません。

public class Krypte {
public static void main (String [] args) {
    int i = 12345;

    String k = Integer.toString(i);
    String G = secure(k.getBytes());
    System.out.println("Encrypted: " + G);

    String U = secure(G.getBytes());
    System.out.println("Decrypted: " + U);
    int X = Integer.parseInt(U);
    System.out.println("As an int: " + X);

}

public static String secure(byte[] msg) {
    // Variables
    int outLength = msg.length;
    byte secret = (byte) 0xAC; // same as 10101100b (Key)
    // XOR kryptering
    for (int i = 0; i < outLength; i++) {
        // encrypting each byte with XOR (^)
        msg[i] = (byte) (msg[i] ^ secret);
    }
    return new String(msg);
}
}
4

1 に答える 1

5

とタイプの間には微妙な(しかし非常に重要な)違いがcharありbyteます。このことを考慮:

class Krypte {
    public static void main (String [] args) {
        int i = 12345;
        String k = Integer.toString(i);
        System.out.println("Before: " + k);    
        String G = secure(k.toCharArray());
        System.out.println("Encrypted: " + G);
        String U = secure(G.toCharArray());
        System.out.println("Decrypted: " + U);
        int X = Integer.parseInt(U);
        System.out.println("As an int: " + X);
    }

    public static String secure(char[] msg) {
        // Variables
        int outLength = msg.length;
        byte secret = (byte) 0xAC; // same as 10101100b (Key)
        // XOR kryptering
        for (int i = 0; i < outLength; i++) {
            // encrypting each byte with XOR (^)
            System.out.println("Byte before: " + msg[i]);
            msg[i] = (char) (msg[i] ^ secret);
            System.out.println("Byte after: " + msg[i]);
        }
        return new String(msg);
    }
}

ある文字値をバイトとXORすると(おそらく)有効な文字が得られるため、これは機能します(証明)。

元のスニペットで何が起こるかを見てみましょう-このデバッグ出力をsecureメソッドのメインループに追加します:

 System.out.println("Byte before: " + msg[i]);
 msg[i] = (byte) (msg[i] ^ secret);
 System.out.println("Byte after: " + msg[i]);

そして、出力は次のようになります。

Byte before: 49
Byte after: -99
Byte before: 50
Byte after: -98
Byte before: 51
Byte after: -97
Byte before: 52
Byte after: -104
Byte before: 53
Byte after: -103

それはまったく問題ありません。最初のgetBytes関数は、プラットフォームのデフォルトの文字セットを使用して、指定された文字列をバイトの配列にエンコードしました。文字はバイト値にエンコードされます。などになります。'1'49'2'50

次に、これらの値をキーとXORし、次のバイトシーケンスを取得します。

-99 -98 -97 -104 -103

最後のステップは簡単なようです。このバイトシーケンスから新しい文字列を作成(および返す)するだけですが、ここで何がうまくいかない可能性がありますか?しかし実際には、それはファンが打撃を受けるまさにそのステップです。)。

コンストラクターは、プラットフォームのデフォルトの文字セットを使用して、Stringこのバイトシーケンスを処理しようとします。実際、一部の文字セットでは、これらのバイトは有効な文字のシーケンスを適切に表しますが、UTF-8ではそうではありません。

...あなたはおそらく次に何が起こるかをすでに推測しています。ここで説明するように、「デコードできない」バイトシーケンスごとに、最初のバイトがいわゆる置換文字に変換され、他のバイトが再試行されます。この特定の例では、最初の呼び出しによって返された文字列に、これらの失敗の兆候が5つありますsecure

この文字列をデコードすることは、ターゲット文字列に関する情報(長さを除く)を格納しないため、まったく意味がありません。そのため、元のコードは最終的に失敗しました。

于 2012-11-14T22:45:10.137 に答える