2017-10-12 1 views
1

Une fois, j'ai vu un exposé de Douglas Crockford où, dans le contexte de javascript, il a mentionné qu'il pourrait être utile de stocker des secrets dans des fermetures.Stockage du texte en clair dans une fermeture java 8

J'imagine que cela pourrait être mis en œuvre comme celui-ci naïvement en Java:

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

Je me demande: Y at-il avantage à le faire? Est-ce que c'est peut-être moins sûr?

Répondre

0

Voici un exemple très "machiné" donc NE L'UTILISEZ PAS DANS VOTRE CODE.

Je pense que l'effet peut être mieux démontré avec un prédicat plutôt qu'avec un fournisseur.

Supposons que vous mettre en œuvre un vérificateur de mot de passe comme suit:

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); 
    } 

} 

Ensuite, vous pouvez créer une instance d'une passe autour de:

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

Et un autre endroit que vous pouvez l'utiliser pour vérifier le mot de passe:

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

Cependant pour le client qui a une instance de PasswordChecker à portée de main, il est pas si difficile d'extraire le mot de passe avec une certaine réflexion:

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

Maintenant, voici la même chose avec une fermeture:

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

Maintenant vous pouvez pas extraire secretPassword du passwordChecker .

+0

J'aime ça - il me semble que vous pourriez faire toutes sortes de fonctionnalités (valdiation, hachage, etc) dans votre prédicat. – Raudbjorn

+0

Désolé, j'ai été "int érupté" par le travail, je mangeais un sandwich en regardant les réponses. Peut-être que j'aurais mis en doute si la question a commencé avec: l'utilisation d'une fermeture protège vos champs contre l'exposition par réflexion. Mais en plus de cela, * la vérification * des mots de passe devrait être implémentée en utilisant des mots de passe de hachage ou SRP ou similaire. Dans ce cas, la fermeture n'a plus de sens. Et votre code introduit une attaque basée sur le temps contre la vérification du mot de passe grâce à la méthode 'equals'. –

+0

Si vous prolongez l'avertissement que le code n'est pas sécurisé et montrez une référence pour votre réclamation que la réflexion ne peut pas fonctionner alors je suis heureux d'upvote. –

3

Aucune raison de le faire. Stockez le mot de passe dans le tableau de caractères, car ils doivent être explicitement convertis en chaîne si vous souhaitez les imprimer.

Prenons l'exemple suivant:

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] 

L'idée principale est que vous pouvez effacer les éléments du tableau, car il n'est pas immuable (@Klitos Kyriacou).

Arrays.fill(charactersPassword, '0'); 

De plus, si vous stockez le mot de passe en texte brut - String, qui est immuable, il sera disponible dans la mémoire pendant une longue période (qui est encore en quelque sorte accesible) jusqu'à ce que le Garbage collector prend en charge il.

Quoi qu'il en soit, il est fortement recommandé de prendre soin de certaines bibliothèques de sécurité qui peuvent gérer beaucoup plus que d'inventer un nouveau moyen (généralement toujours risqué).

+1

L'idée de stocker un mot de passe en caractères est que vous pouvez les effacer, pas tellement qu'ils sont directement disponibles. C'est à l'utilisateur de les effacer, et cette partie manque à votre réponse. –

+0

@MaartenBodewes: Oui, je l'ai maintenant. Merci pour le commentaire. :) –

+0

Non, ce n'est pas comme ça que vous l'effacez! Le tableau d'origine est toujours en attente d'être ramassé dans les poubelles! Vous devez effacer les éléments réels du tableau d'origine. –