2012-03-02 12 views
8

Necesito generar una clave a partir de una cadena, de modo que siempre pueda crear la misma clave a partir de la misma cadena. (Específicamente un objeto Key, para poder usarlo para crear un Cipher para crear un SealedObject)¿Generar clave desde cadena?

¿Es esto posible en Java, y qué combinación de clase/método debería estar buscando para hacerlo?

+0

no 'hashCode()' hacer por usted? si no, ¿por qué? – amit

+0

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

+0

Según tengo entendido, no estoy tratando de crear un SealedObject para encapsular un objeto para su transmisión: No estoy tratando de ofuscar la cadena de texto sin formato en un hash, estoy intentando crear una clave (objeto) –

Respuesta

16

Para el cifrado 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)); 

mismo modo para la obsoleta PBKDF1 y DES inseguro para comunicarse con sistemas heredados o fines de aprendizaje:

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); 
... 

Tenga en cuenta que el número de iteraciones es demasiado bajo también en el último ejemplo.

+0

Gracias. Para ser claros, si realicé lo mismo en el lado del servidor con la misma contraseña, ¿produciría un cifrado que podría usarse para descifrar SealedObject? –

+0

Eso es correcto. Siempre que use las mismas especificaciones de clave y param, tendrá la misma clave. –

+4

Esta hubiera sido una mejor respuesta si eliminaste la primera mitad. El DES está completamente roto hoy, y es peligroso usarlo incluso como ejemplo (las personas podrían copiarlo sin saber que no era seguro). –

0

Puede lograr esto mediante el Cifrado de Java.

En primer lugar, necesitamos dos tarros:

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

Aquí es ejemplo completo de cómo 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); 
    } 
} 

Uso:

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); 

Espero que esto te ayude.

+0

DES puede que ya no ayude a nadie ... –

+0

Tampoco lo hace el cifrado del modo ECB. Tener una clase llamada 'KeyGen' que realiza cifrado/descifrado tampoco da muchas esperanzas. –

4

Quiere utilizar PBKDF2 o bcrypt para esto. El primero es más ampliamente utilizado en mi experiencia. Parece, basado en este comment, que java sí lo admite.

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");