2012-03-02 17 views
8

Potrzebuję wygenerować klucz z łańcucha, tak, że zawsze mogę utworzyć ten sam klucz z tego samego ciągu. (W szczególności obiekt typu Key, dzięki czemu mogę go użyć do utworzenia Szyfrów po to, aby utworzyć SealedObject) Czy jest to możliwe w Javie i na jaką kombinację klas/metod powinienem się tym zwracać?Wygeneruj klucz ze sznurka?

+0

nie będzie "hashCode()" dla ciebie? jeśli nie - dlaczego? – amit

+0

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

+0

Nie tak daleko, jak wiem, ponieważ próbuję utworzyć SealedObject w celu enkapsulacji obiektu do transmisji: Nie próbuję zamazywać ciąg tekstowy w haszyszu, próbuję utworzyć klucz (obiekt) –

Odpowiedz

16

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

Podobnie dla przestarzałe PBKDF1 i niepewny DES do komunikowania się z starszych systemów lub celów uczenia:

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

Należy pamiętać, że liczba iteracji jest zbyt niska także w ostatnim przykładzie.

+0

Dzięki. Dla jasności, jeśli wykonałem to samo po stronie serwera z tym samym hasłem, wygenerowałoby to szyfr, który mógłby zostać użyty do odszyfrowania SealedObject? –

+0

To prawda. Dopóki używasz tych samych parametrów i specyfikacji klawiszy, będziesz mieć ten sam klucz. –

+4

To byłaby lepsza odpowiedź, gdybyś usunął pierwszą połowę. DES jest dziś całkowicie zepsuty i używanie go nawet jako przykładu jest niebezpieczne (ludzie mogą go kopiować, nie wiedząc, że jest to niebezpieczne). –

0

Można to osiągnąć poprzez szyfrowanie Java.

Najpierw trzeba dwa słoiki:

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

Oto pełna przykład jak Data Encryption Standard w Javie:

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

Zastosowanie:

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

Mam nadzieję, że to ci pomoże.

+0

DES już nikomu nie pomoże ... –

+0

Szyfrowanie trybu ECB nie jest również możliwe. Posiadanie klasy o nazwie 'KeyGen' wykonującej szyfrowanie/deszyfrowanie również nie daje wiele nadziei. –

4

Chcesz użyć do tego celu PBKDF2 lub bcrypt. Ten pierwszy jest szerzej stosowany w moim doświadczeniu. Wydaje się, na podstawie tego comment, że java obsługuje to.

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