web-dev-qa-db-fra.com

Comment créer une clé AES aléatoire sécurisée en Java?

Quelle est la méthode recommandée pour générer une clé AES sécurisée et aléatoire en Java, à l'aide du JDK standard?

Dans d'autres publications, j'ai trouvé cela, mais utiliser un SecretKeyFactory pourrait être une meilleure idée:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey();

Ce serait bien si la réponse incluait une explication de la raison pour laquelle c'est un bon moyen de générer la clé aléatoire. Merci!

50
barfuin

J'utiliserais votre code suggéré, mais avec une légère simplification:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // for example
SecretKey secretKey = keyGen.generateKey();

Laissez le fournisseur choisir comment il prévoit obtenir le caractère aléatoire - ne définissez pas un élément qui pourrait ne pas être aussi bon que ce que le fournisseur a déjà sélectionné.

Cet exemple de code suppose ( comme Maarten l'indique ci-dessous ) que vous avez configuré votre fichier Java.security Pour inclure votre fournisseur préféré en haut de la liste. Si vous souhaitez spécifier manuellement le fournisseur, appelez simplement KeyGenerator.getInstance("AES", "providerName");.

Pour obtenir une clé véritablement sécurisée, vous devez utiliser un module de sécurité matérielle (HSM) pour générer et protéger la clé. Les fabricants HSM fourniront généralement un fournisseur JCE qui effectuera toute la génération de clés pour vous, en utilisant le code ci-dessus.

73
Duncan Jones

Utiliser KeyGenerator serait la méthode préférée. Comme Duncan l'a indiqué, je donnerais certainement la taille de la clé lors de l'initialisation. KeyFactory est une méthode à utiliser pour les clés préexistantes.

OK, passons à l'essentiel. En principe, les clés AES peuvent avoir n'importe quelle valeur. Il n'y a pas de "clés faibles" comme dans (3) DES. Il n'y a pas non plus de bits ayant une signification spécifique comme dans (3) bits de parité DES. Donc, générer une clé peut être aussi simple que générer un tableau d'octets avec des valeurs aléatoires et créer un SecretKeySpec autour de celle-ci.

Cependant, la méthode que vous utilisez présente encore des avantages: le KeyGenerator est spécialement créé pour générer des clés. Cela signifie que le code peut être optimisé pour cette génération. Cela pourrait présenter des avantages en termes d’efficacité et de sécurité. Il peut être programmé pour éviter, par exemple, des attaques de canal du côté temporel qui exposeraient la clé. Notez que c’est peut-être déjà une bonne idée de supprimer les byte[] qui contient des informations essentielles car elles peuvent être divulguées dans un fichier d'échange (cela peut néanmoins être le cas de toute façon).

De plus, comme cela a été dit, tous les algorithmes n’utilisent pas des clés totalement aléatoires. Donc, utiliser KeyGenerator faciliterait le passage à d’autres algorithmes. Les chiffrements plus modernes n'accepteront que des clés totalement aléatoires; ceci est considéré comme un avantage majeur par exemple sur DES.

Enfin, et dans mon cas, la raison la plus importante est que la méthode KeyGenerator constitue le seul moyen valable de gérer les clés AES dans un jeton sécurisé (carte à puce, TPM, clé USB ou HSM). Si vous créez le byte[] avec SecretKeySpec puis la clé doit provenir de la mémoire. Cela signifie que la clé peut être placée dans le jeton sécurisé, mais que la clé est exposée en mémoire malgré tout. Normalement, les jetons sécurisés fonctionnent uniquement avec des clés générées dans le jeton sécurisé ou injectées, par exemple, par exemple. une carte à puce ou une cérémonie de clé. Un KeyGenerator peut être fourni avec un fournisseur afin que la clé soit générée directement dans le jeton sécurisé.

Comme indiqué dans réponse de Duncan : spécifiez toujours explicitement la taille de la clé (et tout autre paramètre). Ne comptez pas sur les valeurs par défaut du fournisseur, car cela aura pour effet de ne pas préciser ce que fait votre application et chaque fournisseur peut avoir ses propres valeurs par défaut.

23
Maarten Bodewes

Beaucoup de bons conseils dans les autres messages. C'est ce que j'utilise:

Key key;
SecureRandom Rand = new SecureRandom();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256, Rand);
key = generator.generateKey();

Si vous avez besoin d’un autre fournisseur d’aléatoire, ce que je fais parfois à des fins de test, il suffit de remplacer Rand par

MySecureRandom Rand = new MySecureRandom();
4
Andy