リフレクションを使用してスクラブString
を使用すると、パスワードString
に使用するのと同じくらい安全になりますか?char[]
セキュリティの観点から、パスワードの保存/受け渡しに使用するのがベスト プラクティスと一般的に考えられていchar[]
ます。これは、ガベージ コレクションによってパスワードがクリーンアップされ、メモリが再利用されるよりもかなり前に、コード内でできるだけ早く内容をゼロにできるためです (すべてのトレースをワイプ)、メモリ攻撃の時間枠を制限します。
ただし、char[]
は ほど便利ではないため、必要に応じて をString
「スクラブ」して、 と同じくらい安全にすることができれば便利です。String
String
char[]
以下は、リフレクションを使用して のフィールドをゼロにするメソッドですString
。
この方法は「OK」であり、パスワードString
と同じくらい安全にするという目標を達成していますか?char[]
public static void scrub(String str) throws NoSuchFieldException, IllegalAccessException {
Field valueField = String.class.getDeclaredField("value");
Field offsetField = String.class.getDeclaredField("offset");
Field countField = String.class.getDeclaredField("count");
Field hashField = String.class.getDeclaredField("hash");
valueField.setAccessible(true);
offsetField.setAccessible(true);
countField.setAccessible(true);
hashField.setAccessible(true);
char[] value = (char[]) valueField.get(str);
// overwrite the relevant array contents with null chars
Arrays.fill(value, offsetField.getInt(str), countField.getInt(str), '\0');
countField.set(str, 0); // scrub password length too
hashField.set(str, 0); // the hash could be used to crack a password
valueField.setAccessible(false);
offsetField.setAccessible(false);
countField.setAccessible(false);
hashField.setAccessible(false);
}
簡単なテストを次に示します。
String str = "password";
scrub(str);
System.out.println('"' + str + '"');
出力:
""
注:パスワードはString
定数ではないため、このメソッドを呼び出しても、インターンされた文字列に悪影響を及ぼさないと考えることができます。
また、簡単にするために、このメソッドはかなり「未加工」の状態のままにしています。私がそれを使用する場合、スローされた例外を宣言 (try/catch/ignoring) したり、繰り返されるコードをリファクタリングしたりしません。