2009-12-17 3 views
14
décryptage

Pour le cryptage J'utilise quelque chose comme ceci:moyen facile de stocker/restaurer la clé de chiffrement pour chaîne en java

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

Si j'imprimer aesKey je reçois: « [email protected] » .

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

SecretKey aesKey = [email protected]; 
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm()); 
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted); 

Mais semble son ne fonctionne pas. Existe-t-il un moyen facile d'imprimer la clé après le cryptage sur la console afin que l'utilisateur puisse l'enregistrer (ou s'en souvenir), puis utiliser pour le déchiffrement?

Tout le code est ici: Cannot decrypt cyphertext from text file, symmetric key implement. in java Donc je suis désolé de poster à nouveau mais je ne suis pas sûr Si le code est encore lisible (je suis novice).

+0

S'il vous plaît voir ma réponse à jour. – erickson

Répondre

0

Juste pour référence, la sortie que vous voyez est le résultat de la méthode par défaut toString et le nombre drôle sur la fin est un code de hachage. Voir here. Les codes de hachage ne sont pas forcément réversibles et toString n'est pas forcément garanti pour vous donner assez d'informations pour reconstruire l'objet original (bien que ce soit le cas pour certaines classes).

12

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. Toutefois, pour stocker une clé en toute sécurité sous forme électronique, elle doit être cryptée. Bien sûr, le cryptage de la clé nécessiterait une autre clé (ou mot de passe) & hellip; et ainsi vous avez une régression infinie. Un Java KeyStore peut être utilisé pour stocker des objets SecretKey de cette manière, ce qui est utile lorsque vous avez de nombreuses clés secrètes qui sont toutes protégées par un seul mot de passe «maître». Mais pour protéger une seule clé, cela 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ûre (dans de nombreuses applications, qui peuvent être sur une feuille de papier dans leur portefeuille). Cela peut être aussi simple que d'afficher les octets de la clé codée en hexadécimal, Base-64, ou tout autre encodage de texte, et 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 cela, en utilisant un algorithme comme PBKDF2. Le sel (et peut-être le nombre d'itérations) utilisé pour la dérivation de clé devrait être enregistré quelque part cependant. Un autre inconvénient est que les gens ont tendance à choisir parmi un nombre relativement limité de mots de passe sur le total disponible. Les clés dérivées des mots de passe peuvent donc être plus faciles à deviner que ne le suggère la taille de la clé. Voici une illustration de la technique de base pour persister et 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"); 
+0

Merci pour l'explication. Mais Comment puis-je appeler la clé au lieu d'en générer une (KeyGenerator.getInstance ("AES"). GenerateKey();)? Je peux maintenant imprimer la clé avec getEncoded(), l'utilisateur l'écrira. Mais comment j'appelle la clé de retour? – dave91

+0

Je vois des lectures incohérentes avec la nouvelle partie BigInteger (input, 16) .toByteArray() de ce code. Le plus souvent, sa lecture en 17 octets et en me donnant un 'invalide aes longueur de la clé: erreur de 17 octets lorsque je tente de l'utiliser. Qu'est-ce qui pourrait causer ça? – sapatos

+2

@sapatos si le bit haut de la clé est positionné, 'BigInteger' ajoutera un octet nul au début du tableau d'octets pour éviter qu'il soit interprété comme un nombre négatif. Peut-être qu'au lieu de 'new BigInteger (1, encoded)', vous devriez autoriser la chaîne à être un nombre négatif: 'new BigInteger (encoded)' – erickson

20

J'ai dû le faire moi-même récemment. Et tandis que les réponses d'autres m'ont amené dans la bonne direction, cela aurait pu être plus facile. Donc, voici ma "part" pour la journée, un couple de méthodes d'aide pour la manipulation de clé simple AES.(Notez la dépendance et Apache Commons Codec.)

C'est dans un moment 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"); 
} 
+2

Cela échouera-t-il si le tableau renvoyé par 'getEncoded()' a un octet nul ou si le premier octet a le bit le plus élevé? –

+0

@NiklasB. Fixe, merci de l'avoir souligné. –

+1

_Je suis un fan des fonctions d'utilitaire statiques et des importations statiques :) –

Questions connexes