web-dev-qa-db-fra.com

Un moyen facile de stocker/restaurer la clé de cryptage pour le décryptage de chaîne en java

Pour le cryptage, j'utilise quelque chose comme ceci:

SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey();
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesEncrypted= aesEncrypt.encrypt(StringContent);

Si j'imprime aesKey, je reçois: "javax.crypto.spec.SecretKeySpec@1708d".

Donc, pour le cryptage, je voudrais demander à l'utilisateur la clé mais je ne sais pas comment et quel format devrait être. Mon plan ressemblait à ceci:

SecretKey aesKey = javax.crypto.spec.SecretKeySpec@1708d;
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted);

Mais semble que ça ne marche pas. Existe-t-il un moyen simple d’imprimer la clé après le chiffrement sur la console afin que l’utilisateur puisse la sauvegarder (ou la mémoriser), puis utiliser pour le déchiffrement?

Tout le code est ici: Impossible de déchiffrer le cyphertext du fichier texte, implémenter une clé symétrique. en Java Donc, je suis désolé de poster à nouveau, mais je ne suis pas sûr si le code est même lisible (je suis novice).

15
dave91

J'ai dû le faire moi-même récemment. Et tandis que les autres réponses ici me menaient dans la bonne direction, cela aurait pu être plus facile. Voici donc ma "part" pour la journée, quelques méthodes d'assistance pour la manipulation de clés AES simples. (Notez la dépendance sur Apache Commons et Codec.)

Tout cela se trouve maintenant dans un dépôt Git: github.com/stuinzuri/SimpleJavaKeyStore

import static org.Apache.commons.codec.binary.Hex.*;
import static org.Apache.commons.io.FileUtils.*;
import Java.io.*;
import Java.security.NoSuchAlgorithmException;
import javax.crypto.*;
import org.Apache.commons.codec.DecoderException;

public static SecretKey generateKey() throws NoSuchAlgorithmException
{
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(256); // 128 default; 192 and 256 also possible
    return keyGenerator.generateKey();
}

public static void saveKey(SecretKey key, File file) throws IOException
{
    char[] hex = encodeHex(key.getEncoded());
    writeStringToFile(file, String.valueOf(hex));
}

public static SecretKey loadKey(File file) throws IOException
{
    String data = new String(readFileToByteArray(file));
    byte[] encoded;
    try {
        encoded = decodeHex(data.toCharArray());
    } catch (DecoderException e) {
        e.printStackTrace();
        return null;
    }
    return new SecretKeySpec(encoded, "AES");
}
21
Stu Thompson

La plupart des instances Java Key sont représentées par une chaîne d'octets résultant de leur méthode getEncoded() . C'est ce qui doit être stocké afin de reconstruire la clé plus tard.

Cependant, pour stocker une clé en toute sécurité sous forme électronique, il convient de la chiffrer. Bien sûr, le cryptage de la clé nécessiterait une autre clé (ou mot de passe)… et vous obtenez une régression infinie. Une KeyStore Java peut être utilisée pour stocker les objets SecretKey de cette manière, ce qui est utile lorsque vous avez plusieurs clés secrètes protégées par un seul mot de passe "maître". Mais protéger une seule clé n'a pas beaucoup de sens.

Une alternative consiste à présenter la clé à l'utilisateur sous une forme qui peut être stockée de manière sécurisée (dans de nombreuses applications, il peut s'agir d'un bout de papier dans son portefeuille). Cela peut être aussi simple que d'afficher les octets de la clé codée au format hexadécimal, Base-64 ou un autre codage de texte et de demander à l'utilisateur de l'écrire.

Une autre approche consiste à permettre à l'utilisateur de choisir un mot de passe mémorable et de générer une clé avec celui-ci, à l'aide d'un algorithme tel que PBKDF2. Le sel (et peut-être le nombre d'itérations) utilisé pour la dérivation de clé doit cependant être enregistré quelque part. Un autre inconvénient est que les utilisateurs ont tendance à choisir parmi un nombre relativement limité de mots de passe sur le total disponible. Ainsi, les clés dérivées de mots de passe peuvent être plus faciles à deviner que ce que la taille de la clé suggère.


Voici une illustration de la technique de base permettant de conserver et de reconstituer une clé secrète.

byte[] encoded = aesKey.getEncoded();
/* Now store "encoded" somewhere. For example, display the key and 
   ask the user to write it down. */
String output = Base64.getEncoder().withoutPadding().encodeToString(encoded);
System.out.println("Keep it secret, keep it safe! " + output);

...

/* At some point, you need to reconstitute the key. Let's say the user 
   enters it as a base-64 number that you convert to bytes. */
String input = ... ;
byte[] encoded = Base64.getDecoder().decode(input);
SecretKey aesKey = new SecretKeySpec(encoded, "AES");
13
erickson

J'ai stocké des clés dans des fichiers de clés Java. Voici un article qui peut vous aider

http://www.informit.com/articles/article.aspx?p=170967&seqNum=3

4
BillMan

Juste pour référence, la sortie que vous voyez est le résultat de la méthode toString par défaut et le chiffre amusant à la fin est un code de hachage. Voir ici . Les codes de hachage sont par nature non réversibles et il n'est pas forcément garanti que toString vous fournisse suffisamment d'informations pour reconstruire l'objet d'origine (bien que ce soit le cas pour certaines classes).

0
Dan