文字列を予め暗号化しておき,実行時,暗号化された文字列が参照される直 前に復号する難読化手法です.
| Name | Default Value | Description |
| provider | empty | JCE プロバイダを指定する.空文字の場合はデフォルトのプロバイダを用いる.初期値は空文字列. |
| algorithm | DES/56 | 文字列を暗号化するときに用いるアルゴリズムと鍵長を「アルゴリズム名/鍵長」のフォーマットで指定する.それぞれ用いることができるのは JCE プロバイダが提供するもののみ. |
| key | empty | 暗号化するときに用いるの鍵.空文字列の場合は難読化時に乱数でキーを生成する.初期値は空文字列. |
文字列暗号難読化を施した例を以下に示します.難読化前のソースコード中 には World や Hello などの文字列を見つけることができますが,難読化後の ソースコードからは何が出力されるのかは全くわかりません.
ここで示した難読化後のプログラムはバイトコード表現をそのままソースコー ドに直しているだけなので,__decrypt メソッド内の try-catch 節は実際に はありません.
public class HelloWorld{
public String greeting(){
return greeting("World");
}
public String greeting(String name){
if(name == null){
return greeting();
}
return new String(new StringBuffer("Hello ").append(name));
}
public static void main(String[] args){
String name = null;
if(args.length > 0){
name = args[0];
}
System.out.println(new HelloWorld().greeting(name));
}
}
public class HelloWorld{
public String greeting(){
return greeting(__decrypt("380aeeae1b7701ce"));
}
public String greeting(String name){
if(name == null){
return greeting();
}
return new String((new StringBuffer(__decrypt("b710eaebac3c751c"))).append(name));
}
public static void main(String[] args){
String name = null;
if(args.length > 0){
name = args[0];
}
System.out.println(new HelloWorld().greeting(name));
}
private static String __decrypt(String name){
try{
SecretKeySpec skeySpec = new SecretKeySpec(
new byte[] {
(byte)2, (byte)179, (byte)59, (byte)253,
(byte)181, (byte)55, (byte)185, (byte)196,
},
"DES"
);
Cipher cipher = Cipher.getInstance("DES", "SunJCE");
cipher.init(2, skeySpec);
byte[] nameData = new byte[name.length() / 2];
for(int i = 0; i < nameData.length; i++)
nameData[i] = (byte)Integer.parseInt(name.substring(i * 2, i * 2 + 2), 16);
return new String(cipher.doFinal(nameData));
} catch(Exception e){
}
return null;
}
}