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 aléatoire sécurisée en Java, en utilisant le JDK standard?

dans d'autres messages, j'ai trouvé ceci, 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 formidable si la réponse inclus une explication de pourquoi c'est une bonne façon de générer la clé aléatoire. Merci!

46
demandé sur Duncan Jones 2013-08-14 13:55:47

3 réponses

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 l'aléatoire - ne pas définir quelque chose qui ne peut 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, il suffit d'appeler KeyGenerator.getInstance("AES", "providerName"); .

pour une clé vraiment sécurisée, vous devez utiliser un module de sécurité Matériel (HSM) pour générer et protéger la clé. Les fabricants HSM fournissent 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
répondu Duncan Jones 2017-05-23 12:02:26

utilisant 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, donc allons droit au but. 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)des bits de parité. Donc générer une clé peut être aussi simple que générer un tableau d'octets avec des valeurs aléatoires, et la création d'un SecretKeySpec autour de lui.

mais il y a encore des avantages à la méthode que vous utilisez: 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. Ce pourrait avoir des avantages d'efficacité et de sécurité. Elle pourrait être programmée pour éviter une attaque de canal latéral de synchronisation qui exposerait la clé, par exemple. Notez qu'il peut déjà être un bonne idée d'effacer tout byte[] qui contiennent des informations clés car elles peuvent être divulguées dans un fichier de pagination (ce qui 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. Ainsi, l'utilisation de KeyGenerator faciliterait le passage à d'autres algorithmes. Les chiffrements plus modernes n'accepteront que les clés entièrement aléatoires; ceci est considéré comme un avantage majeur par rapport par exemple à DES.

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

comme indiqué dans réponse de Duncan : toujours spécifier explicitement la taille de la clé (et tout autre paramètre). Ne comptez pas sur les fournisseurs par défaut car ce va rendre difficile ce que fait votre application, et chaque fournisseur peut avoir ses propres défauts.

21
répondu Maarten Bodewes 2017-05-23 10:31:06

Beaucoup de bonnes advince dans les autres postes. 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 randomness, ce que je fais parfois à des fins de test, il suffit de remplacer rand par

MySecureRandom rand = new MySecureRandom();
3
répondu Andy 2017-08-22 08:32:30