2012-03-02 5 views
8

J'ai besoin de générer une clé à partir d'une chaîne, de sorte que je peux toujours créer la même clé à partir de la même chaîne. Est-ce possible en Java, et quelle combinaison classe/méthode devrais-je regarder pour faire ainsi?Générer une clé à partir d'une chaîne?

+0

est ce que 'hashCode()' ne fera pas pour vous? sinon, pourquoi? – amit

+0

http://en.wikipedia.org/wiki/Java_hashCode()#The_java.lang.String_hash_function – JProgrammer

+0

Pas pour autant que je sache, parce que je suis en train de créer un SealedObject pour encapsuler un objet pour la transmission: Je n'essaie pas d'obscurcir la chaîne de texte en un hachage, j'essaye de créer une clé (objet) –

Répondre

16

Pour le cryptage AES:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256); 
SecretKey tmp = factory.generateSecret(spec); 
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
cipher.init(Cipher.ENCRYPT_MODE, secret); 

byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); 
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8")); 

// reinit cypher using param spec 
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); 

De même pour le dépréciée PBKDF1 et DES non sécurisé pour communiquer avec systèmes existants ou fins d'apprentissage:

byte[] salt = { 
    (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c, 
    (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 
}; 

int count = 20; 

PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count); 
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray()); 
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); 

Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); 
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec); 

SealedObject sealed = new SealedObject(object, cipher); 
... 

Notez que le nombre d'itérations est trop faible aussi bien dans le dernier exemple.

+0

Merci. Juste pour être clair, si je faisais la même chose du côté du serveur avec le même mot de passe, cela produirait un chiffrement qui pourrait être utilisé pour décrypter le SealedObject? –

+0

C'est exact. Tant que vous utilisez les mêmes spécifications param et key, vous aurez la même clé. –

+4

Cela aurait été une meilleure réponse si vous avez supprimé la première moitié. DES est complètement cassé aujourd'hui, et il est dangereux de l'utiliser même à titre d'exemple (les gens pourraient le copier sans savoir que c'était dangereux). –

0

Vous pouvez y parvenir en cryptant Java.

Au début, vous avez besoin de deux pots:

  1. bcmail-jdk16-1.46.jar
  2. bcprov-jdk16-1.46.jar

Voici exemple complet de la façon de Data Encryption Standard en Java:

import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.KeyGenerator; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 

import org.bouncycastle.util.encoders.Base64; 


public class KeyGen { 
    private SecretKey key; 
    private Cipher ecipher; 
    private Cipher dcipher; 
    private static KeyGen keyGen; 

    private KeyGen() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{ 
     key = KeyGenerator.getInstance("DES").generateKey(); 
     ecipher = Cipher.getInstance("DES"); 
     dcipher = Cipher.getInstance("DES"); 
     ecipher.init(Cipher.ENCRYPT_MODE, key); 
     dcipher.init(Cipher.DECRYPT_MODE, key); 
    } 

    public static KeyGen getInstance() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException { 
     if(keyGen == null) { 
      keyGen = new KeyGen(); 
     } 
     return keyGen; 
    } 

    public String encrypt(String str) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { 
     byte[] utf8 = str.getBytes("UTF8"); 
     byte[] enc = ecipher.doFinal(utf8); 
     return new String(Base64.encode(enc)); 
    } 

    public String decrypt(String str) throws IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException { 
     byte[] dec = Base64.decode(str); 
     byte[] utf8 = dcipher.doFinal(dec); 
     return new String(utf8, "UTF8"); 
    } 

    public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { 
     KeyGen keyGen = KeyGen.getInstance(); 
     String string = "JOYMAA"; 
     String enc = keyGen.encrypt(string); 
     System.out.println(enc); 
     String dec = keyGen.decrypt(enc); 
     System.out.println(dec); 
    } 
} 

Utilisation:

KeyGen keyGen = KeyGen.getInstance(); 
String string = "JOYMAA"; 
String enc = keyGen.encrypt(string); 
System.out.println(enc); 
String dec = keyGen.decrypt(enc); 
System.out.println(dec); 

J'espère que cela vous aidera.

+0

DES n'aidera plus personne ... –

+0

Le cryptage en mode ECB n'est pas non plus possible. Avoir une classe nommée KeyGen qui effectue le cryptage/décryptage ne donne pas beaucoup d'espoir non plus. –

4

Vous voulez utiliser PBKDF2 ou bcrypt pour cela. Le premier est plus largement utilisé dans mon expérience. Il semble, basé sur ce comment, que Java supporte cela.

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256); 
SecretKey tmp = factory.generateSecret(spec); 
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
Questions connexes