2017-10-12 15 views
1

私はかつてDouglas Crockfordの話を見ましたが、javascriptの文脈では、クロージャに秘密を格納すると便利であると述べました。私はこれを想像Java 8クロージャ内に平文を格納

は単純にJavaでこのように実装することができます

public static Supplier<String> passwordStore(String encryptedPassword){ 
    String plainTextPassword = encryptedPassword; //do some decryption 
    return() -> plainTextPassword; 
} 

私は疑問に思う:これを行うにどんなメリットがありますか?それは多分何らかの形で安全性が低いのでしょうか?

答えて

0

ここには非常に「設計された」例がありますのであなたのコードには使用しないでください

私は、サプライヤではなく述語を使って効果を実証できると思います。

は、次のようにパスワードチェッカーを実装すると仮定します

public class PasswordChecker { 

    private final String secretPassword; 

    public PasswordChecker(String secretPassword) { 
     this.secretPassword = secretPassword; 
    } 

    public boolean test(String password) { 
     return Objects.equals(this.secretPassword, password); 
    } 

} 

その後、あなたの周りのパスにそれをインスタンスを作成することができます。

final PasswordChecker passwordChecker = new PasswordChecker("changeit"); 

そしてどこかにあなたがパスワードを確認するためにそれを使用することができました:

assertThat(passwordChecker.test("foobar")).isFalse(); 

ただし、のインスタンスを持つクライアントの場合手で、いくつかの反射とパスワードを抽出するためにそれほど難しいことではありません。

Field secretPasswordField = passwordChecker.getClass().getDeclaredField("secretPassword"); 
    secretPasswordField.setAccessible(true); 
    String secretPassword = (String) secretPasswordField.get(passwordChecker); 
    System.out.print(secretPassword); 

は今ここにクロージャと同じことだ:

final String secretPassword = "changeit"; 
final Predicate<String> passwordChecker = password -> Objects.equals(secretPassword, password); 

は今、あなたはpasswordCheckerからsecretPasswordを抽出することはできません。

+0

私はこれが好きです。あなたの述語にあらゆる種類の機能(valdiation、hashingなど)を焼くことができます。 – Raudbjorn

+0

申し訳ありませんが、私は仕事によって "int erupted"を得ました、私は答えを見るときにサンドイッチを食べていました。たぶん私は質問が始まった場合、アップアップしたでしょう:閉鎖を使用することは、あなたのフィールドを反射から守ることから保護します。しかし、それ以外にパスワードの検証*はパスワードハッシュやSRPなどを使って実装する必要があります。その場合、クロージャーはもう意味をなさない。あなたのコードでは、 'equals'メソッドを使ってパスワードの検証に対して時間ベースの攻撃を導入しています。 –

+0

コードが安全でない旨の警告を表示し、反射がうまくいかないという主張の参照を表示すると、私はupvoteに満足しています。 –

3

これを行う理由はありません。パスワードを文字列に格納します。文字列を印刷したい場合は文字列に明示的に変換する必要があるためです。

は、以下の例を考えてみます

String stringPassword = "password"; 
char[] charactersPassword = new char[]{'p','a','s','s','w','o', 'r', 'd'}; 

System.out.println("Password: " + stringPassword);  // Password: password 
System.out.println("Password: " + charactersPassword); // Password: [[email protected] 

を主なアイデアは、それが(@Klitos Kyriacou)不変ではありませんので、あなたは、配列の項目をクリアすることができます。あなたはプレーンテキストとしてパスワードを保存する場合

Arrays.fill(charactersPassword, '0'); 

また、 - 不変である文字列、ガベージコレクタはの世話をするまで、それは(まだ何とかづけしている)長時間メモリに利用できるようになりますそれ。

とにかく、新しい(通常はまだ危険な)方法を発明するよりもはるかに多くを扱うことができるセキュリティライブラリを調べることを強くお勧めします。

+1

パスワードを文字で保存するというアイデアは、パスワードをクリアすることができ、直接利用できるほどではないということです。それをクリアするのはユーザーの責任です。この部分はあなたの答えにはありません。 –

+0

@MaartenBodewes:はい、今すぐ入手しました。コメントありがとうございました。 :) –

+0

いいえ、それはあなたがそれをクリアする方法ではありません!元の配列はまだガベージコレクションされるのを待っています!元の配列の実際の要素をクリアする必要があります。 –

関連する問題