Javaコードを見てみましょう。
String c = new String(Test.encrypt((new String("thevalue")).getBytes(),
(new String("mykey")).getBytes()));
...
System.out.println("Base64 encoded String:" +
new sun.misc.BASE64Encoder().encode(c.getBytes()));
ここで行っていることは次のとおりです。
- システムのデフォルトのエンコーディングを使用して、プレーンテキストの文字列をバイトに変換します
- システムのデフォルトのエンコーディングを使用して、キーをバイトに変換します
- バイトを暗号化する
- システムのデフォルトのエンコーディングを使用して、暗号化されたバイトを文字列に変換し直します
- システムのデフォルトのエンコーディングを使用して、暗号化された文字列をバイトに変換し直します
- Base64を使用してこれらの暗号化されたバイトをエンコードします。
問題はステップ4にあります。これは、任意のバイト配列がシステムのデフォルトエンコーディングの文字列を表し、この文字列を再度エンコードすると同じbyte[]が得られることを前提としています。これは、一部のエンコーディング(ISO-8859
たとえば、シリーズ)には有効ですが、他のエンコーディングには有効ではありません。Javaでは、特定のエンコーディングで一部のバイト(またはバイトシーケンス)を表現できない場合、他の文字に置き換えられ、後で再変換するためにバイト63(ASCII ?
)にマップされます。実際、ドキュメントには次のようにも書かれています。
指定されたバイトがデフォルトの文字セットで有効でない場合のこのコンストラクターの動作は指定されていません。
あなたの場合、これを行う理由はまったくありません。encrypt
メソッドが直接出力するバイトを使用して、Base64に変換するだけです。
byte[] encrypted = Test.encrypt("thevalue".getBytes(),
"mykey".getBytes());
System.out.println("Base64 encoded String:"+ new sun.misc.BASE64Encoder().encode(encrypted));
new String("...")
(これはあなたの問題とは関係ありませんが、ここで余分なコンストラクター呼び出しを削除したことにも注意してください。)
覚えておくべきポイント:文字列のエンコードに由来しない任意のbyte[]を文字列に変換しないでください。暗号化アルゴリズム(および復号化を除く他のほとんどの暗号化アルゴリズム)の出力は、文字列に変換してはならないデータのカテゴリに確実に属します。
また、ポータブルプログラムが必要な場合は、システムのデフォルトのエンコーディングを使用しないでください。