I need to generate a Key from a string, such that I can always create the same key from the same string. (Specifically a Key object, so that I can use it to create a Cipher in t
You can achieve this by Encryption of Java.
At first you need two jars:
Here is complete example of how to Data Encryption Standard in 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);
}
}
Usage:
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);
Hope this will help you.
For AES encryption:
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));
Similarly for the deprecated PBKDF1 and insecure DES for communicating with legacy systems or learning purposes:
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);
...
Note that the iteration count is too low as well in the last example.
You want to use PBKDF2 or bcrypt for this. The former is more widely used in my experience. It appears, based on this comment, that java does support this.
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");