2012-09-03 3 views

Répondre

23

Non, vous devez éviter le constructeur SecureRandom(byte[]). Il est à la fois dangereux et non portable.

Il est non portable car il se comporte différemment sur Windows par rapport aux autres systèmes d'exploitation.

Sur la plupart des systèmes d'exploitation, l'algorithme par défaut est "NativePRNG", qui obtient des données aléatoires du système d'exploitation (généralement "/dev/random") et ignore le germe fourni.

Sous Windows, l'algorithme par défaut est "SHA1PRNG", qui combine votre seed avec un compteur et calcule un hachage du résultat.

Ceci est une mauvaise nouvelle dans votre exemple, car l'entrée (l'heure UTC actuelle en millisecondes) a une plage relativement petite de valeurs possibles. Par exemple, si un attaquant sait que le RNG a été ensemencé dans les dernières 48 heures, il peut réduire la graine à moins de 2 valeurs possibles, c'est-à-dire que vous n'avez que 27 bits d'entropie.

Si, par contre, vous aviez utilisé le constructeur SecureRandom() par défaut sous Windows, il aurait appelé la fonction native CryptoGenRandom pour obtenir un amorçage de 128 bits. Donc, en spécifiant votre propre graine, vous avez affaibli la sécurité.

Si vous voulez vraiment remplacer le germe par défaut (par exemple pour les tests unitaires), vous devez également spécifier l'algorithme. Par exemple.

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
sr.setSeed("abcdefghijklmnop".getBytes("us-ascii")); 

Voir aussi How to solve performance problem with Java SecureRandom?
et ce blog: http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

+1

Notez que le code que vous fournissez initialise le générateur pseudo-aléatoire avec seulement la chaîne encodée en entrée. Donc, il créerait le même aléatoire à chaque fois.Je pense que vous vouliez montrer exactement cela, mais vous pourriez vouloir le rendre plus clair dans la réponse (car il n'est certainement pas sécurisé). Cela pourrait aussi être différent si n'importe quel autre fournisseur proposait "SHA1PRNG", donc à cet égard c'est un peu dangereux. –

+0

C'est la réponse à laquelle je m'attendais, merci! –

+0

@MaartenBodewes Pourquoi pensez-vous que la graine est ignorée lors de l'utilisation de "NativePRNG"? –

1

Le code est raisonnablement sûr car il n'utilise pas seulement la graine donnée pour ensemencer le randomiseur.

Ce n'est pas beaucoup plus aléatoire que de simplement utiliser.

SecureRandom randomizer = new SecureRandom(); 
+2

Oui, probablement en utilisant la valeur par défaut est meilleure - on suppose que les concepteurs de l'algorithme choisiraient un bon schéma d'ensemencement. Le schéma ci-dessus affaiblit probablement la graine en la convertissant en représentation de caractères. –

+4

Il est considérablement * moins * aléatoire que d'utiliser le constructeur par défaut. – EJP

+0

@PeterLawrey Ici, vous recommandez d'utiliser 'new SecureRandom()' mais à [this] (http://stackoverflow.com/a/8572501/1317865) vous dites d'utiliser 'System.nanoTime'. Dans [this] (http://crypto.stackexchange.com/questions/12306/generate-random-in-secure-message-transfer), devrais-je utiliser 'new SecureRandom()' ou 'System.nanoTime'. Merci d'avance – Favolas

2

Je pense qu'il est préférable de laisser la graine SecureRandom elle-même. Ceci est fait en appelant nextBytes immédiatement après sa création (l'appel de setSeed l'empêchera). Vous souhaitez utiliser SHA1PRNG car il garantit une implémentation rapide et non bloquante même sous Linux, où la valeur par défaut ne l'est pas.

+2

Si l'appel de 'nextBytes()' est prévu pour juste donner un coup de pied de l'ensemencement, je n'utiliserais pas 512 byes mais seulement 1 pour des raisons d'efficacité. – eckes

Questions connexes