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


Quelle est la manière recommandée de générer une clé AES sécurisée et aléatoire en Java, en utilisant le JDK standard?

Dans d'autres articles, 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 génial 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!

Author: Duncan Jones, 2013-08-14

3 answers

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 sélectionner la façon dont il prévoit d'obtenir le caractère aléatoire - ne définissez pas quelque chose qui peut ne pas être aussi bon que ce que le fournisseur a déjà sélectionné.

Cet exemple de code suppose ( comme le souligne Maarten 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 - KeyGenerator.getInstance("AES", "providerName");.

Pour un clé vraiment 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 fera toute la génération de clés pour vous, en utilisant le code ci-dessus.

 65
Author: Duncan Jones, 2017-05-23 12:02:26

L'utilisation de 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 qui doit être utilisée pour les clés préexistantes.

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

Mais il y a toujours des avantages à la méthode que vous utilisez: le KeyGenerator est spécifiquement créé pour générer des clés. Cela signifie que le code peut être optimisé pour cette génération. Ce pourrait avoir des avantages en termes d'efficacité et de sécurité. Il peut être programmé pour éviter une attaque de canal latéral de synchronisation qui exposerait la clé, par exemple. Notez qu'il peut déjà être une bonne idée d'effacer tout byte[] qui contient des informations clés car elles peuvent être divulguées dans un fichier d'échange(cela peut être le cas de toute façon).

De plus, comme dit, tous les algorithmes n'utilisent pas des clés entièrement aléatoires. Donc, l'utilisation de KeyGenerator faciliterait le passage à d'autres algorithmes. Les chiffrements plus modernes n'accepteront cependant que des clés entièrement aléatoires; ceci est considéré comme un avantage majeur par rapport aux DES.

Enfin, et dans mon cas la raison la plus importante, c'est que la méthode KeyGenerator est le seul moyen valable de gérer les clés AES dans un jeton sécurisé (carte à puce, TPM, jeton USB ou HSM). Si vous créez le byte[] avec le SecretKeySpecalors 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 indépendamment. Normalement, les jetons sécurisés ne fonctionnent qu'avec des clés générées dans le jeton sécurisé ou injectées par exemple par une carte à puce ou une cérémonie de clés. Un KeyGenerator peut être fourni avec un fournisseur afin que la clé soit directement générée dans le jeton sécurisé.

Comme indiqué dans Duncan réponse : spécifiez toujours explicitement la taille de la clé (et tous les autres paramètres). Ne vous fiez pas aux valeurs par défaut du fournisseur, car ce ne rendra pas clair ce que fait votre application, et chaque fournisseur peut avoir ses propres valeurs par défaut.

 21
Author: Maarten Bodewes, 2017-05-23 10:31:06

Beaucoup de bons advince 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 de caractère aléatoire, ce que je fais parfois à des fins de test, remplacez simplement rand par

MySecureRandom rand = new MySecureRandom();
 3
Author: Andy, 2017-08-22 08:32:30