0

昨日、次の質問をしましたが、実際の問題の詳細が記載されていなかったため、あまり注目されませんでした。

Eclipse:テキストエディタでUTF-8エンコーディングを使用すると、文字列が正しく機能しなくなりますが、どうすれば修正できますか?

何が起こっているのかを明確に理解できるように、問題を可能な限り分析するように努めます。

私は、教育目的でSimplifiedDESアルゴリズムを実装することになっている大学のプロジェクトを持っています。このアルゴリズムは、8ビットデータを暗号化するために10ビットキーを使用する暗号化アルゴリズムです。

実装では、任意の文字列の暗号化を含めたいと思いました。

だから私は8ビットの暗号化のためのコードを書きました、そしてそれはすべての種類の入力のために完全にうまくいきました。文字列暗号化のサポートを含めるために、関数を使用してString.getBytes()、文字列のすべてのバイトを変数内に保存しましたbyte[] data

そして、私はこの論理に従いました:

int i;
for(i=0; i< data.length; i++)
    data[i] = encrypt(data[i]);

復号化のために、私はこのロジックに従いました。

int i;
for(i=0; i< data.length; i++)
    data[i] = encrypt(data[i]);

mainこれが関数の実際のコードです

public static void main(String[] args){

    short K = (short) Integer.parseInt("1010010001",2);
    SDEncryption sdes = new SDEncryption(K); //K is the 10 bit key

    String test = "INFO BOB 57674";

    //let's encrypt the String test
    String enc = sdes.encrypt(test.getBytes());

    //let's decrypt the encrypted String of the initial String
    String dec = sdes.decrypt(enc.getBytes());
}

Cp1252であるデフォルトのエンコーディングを使用する。文字列を暗号化しようとすると、次の結果が得られました。

Initial Text: INFO BOB 57674
Encrypted Text: ÅO [áa[aá»j×jt
Decrypted Text: INFO BOB 57674

データを暗号化および復号化するたびに実際のビット表現を確認するために、各文字列のすべてのデータを表示するために次の関数を作成しました。

public void show(byte[] data){
    //εμφάνιση των 
    //note how the Greek letters aren't displayed at all under Cp1252

    int i;
    for(i=0;i<data.length;i++){

        short mask = (short) (1<<7); //10000000
        while(mask>0){
            if((data[i]&mask) == 0)
                System.out.print("0");
            else
                System.out.print("1");

            mask = (short) (mask >> 1);
        }
        if(i < data.length - 1){

            System.out.print(" ");
        }
    }
    System.out.println();
}

だから私は次の結果を得ました:

Initial Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100
Encrypted Text(binary): 11000101 01001111 00100000 01011011 11100001 01100001 01011011 01100001 11100001 10111011 01101010 11010111 01101010 01110100
Decrypted Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100

すべてが期待どおりに機能しているようです。ただし、コードエディタでギリシャ文字をサポートするには、エンコーディングをUTF-8に変更する必要がありました。

すべてを再度実行した後、次の結果が得られました。

Initial Text: INFO BOB 57674
Encrypted Text: �O [�a[a�j�jt
Decrypted Text: ���NFO���BOB���7���74

復号化されたテキストの一部の単語が正しく表示されていることに注目してください。たとえばNFOBOB。EclipseがUTF-8のルールに従ったビットのシーケンスを認識しないかのように、ビット操作に何らかの問題があるように私には思えます。

バイナリ形式の結果は次のとおりです。

Initial Text(binary): 01001001 01001110 01000110 01001111 00100000 01000010 01001111 01000010 00100000 00110101 00110111 00110110 00110111 00110100
Encrypted Text(binary): 11101111 10111111 10111101 01001111 00100000 01011011 11101111 10111111 10111101 01100001 01011011 01100001 11101111 10111111 10111101 01101010 11101111 10111111 10111101 01101010 01110100
Decrypted Text(binary): 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 01001110 01000110 01001111 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 01000010 01001111 01000010 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 00110111 11101111 10111111 10111101 11101111 10111111 10111101 11101111 10111111 10111101 00110111 00110100

今、私は問題の鉱石をはっきりと見ることができます。UTF-8が文字列にさらにバイトを追加しているようです。しかし、理由はわかりません。つまり、初期テキストのバイト数は同じように見えるのに、なぜこれらのバイトが暗号化後に追加され、復号化後にさらに追加されるのでしょうか。

何か助けていただければ幸いです。前もって感謝します!

4

1 に答える 1

4

実行するたびにString.getBytes()、プラットフォームのデフォルトエンコーディングを暗黙的に使用して、文字をバイトに変換します。文字列にプラットフォームのデフォルトのエンコーディングを使用して表現できない文字が含まれている場合、情報が失われます。したがって、UTF8のように、地球上のすべての文字をサポートする明示的なエンコーディングを使用してくださいstring.getBytes("UTF8")

同様に、を実行するときはnew String(bytes)、プラットフォームのデフォルトのエンコーディングを使用してバイトを文字に変換します。バイトが実際に別のエンコーディングを使用してテキストエンコードされている場合、または文字ではなく、純粋にバイナリ情報である場合も、情報が失われます。

暗号化は二項演算です。バイトを受け取り、他のバイトを返します。すべてのバイトが有効な文字を表すわけではないため、エンコーディングが何であれ、バイトを盲目的に文字に変換することはできません。バイナリ情報(暗号化されたテキストなど)を文字列に変換する場合は、HexまたはBase64エンコーディングを使用します。

したがって、暗号化プロセスは次のようになります。

String clearText = ...:
byte[] clearTextAsBytes = clearText.getBytes("UTF8");
byte[] encryptedBinary = encrypt(clearTextAsBytes);
String encryptedBinaryAsPrintableChars = toBase64(encryptedBinary);

また、復号化プロセスは対称的である必要があります。

String encryptedBinaryAsPrintableChars = ...;
byte[] encryptedBinary  = fromBase64(encryptedBinaryAsPrintableChars);
byte[] decryptedTextAsBytes = decrypt(encryptedBinary);
String decryptedText = new String(decryptedTextAsBytes, "UTF8");
于 2013-01-05T15:56:49.313 に答える