views:

16698

answers:

5

I need to implement 256 bit AES encryption, but all the examples I have found online use a "KeyGenerator" to generate a 256 bit key, but I would like to use my own passkey. How can I create my own key? I have tried padding it out to 256 bits, but then I get an error saying that the key is too long. I do have the unlimited jurisdiction patch installed, so thats not the problem :)

Ie. The KeyGenerator looks like this ...

// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available

// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();

Code taken from here

EDIT

I was actually padding the password out to 256 bytes, not bits, which is too long. The following is some code I am using now that I have some more experience with this.

byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)

The "TODO" bits you need to do yourself :-)

+1  A: 

What I've done in the past is hash the key via something like SHA256, then extract the bytes from the hash into the key byte[].

After you have your byte[] you can simply do:

SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(clearText.getBytes());
DarkSquid
+1  A: 

Generating your own key from a byte array is easy:

byte[] raw = ...; // 32 bytes in size for a 256 bit key
Key skey = new javax.crypto.spec.SecretKeySpec(raw, "AES");

But creating a 256-bit key isn't enough. If the key generator cannot generate 256-bit keys for you, then the Cipher class probably doesn't support AES 256-bit either. You say you have the unlimited jurisdiction patch installed, so the AES-256 cipher should be supported (but then 256-bit keys should be too, so this might be a configuration problem).

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skey);
byte[] encrypted = cipher.doFinal(plainText.getBytes());

A workaround for lack of AES-256 support is to take some freely available implementation of AES-256, and use it as a custom provider. This involves creating your own Provider subclass and using it with Cipher.getInstance(String, Provider). But this can be an involved process.

waqas
+12  A: 
erickson
Argh. Salts are not necessary for symmetric encryption. IVs serve a similar purpose, and are prepended to the ciphertext by most (all?) crypto libraries.
Nick Johnson
@Nick: Read PKCS #5. Salts are necessary for PBKDF2, which is why the API for password-based encryption requires them as input for key derivation. Without salts, a dictionary attack could be used, enabling a pre-computed list of the most likely symmetric encryption keys. Cipher IVs and key-derivation salts serve different purposes. IVs allow one reuse the same key for multiple messages. Salts prevent dictionary attacks on the key.
erickson
Does this usage of SecureKey and PBEKeySpec produce a Password-based key that is RFC2898-compliant? http://www.ietf.org/rfc/rfc2898.txt
Cheeso
Yes, that is the "PBKDF2" of the SecretKeyFactory algorithm name. It is referring to PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
erickson
If you were storing encrypted data in a database using the method above, would you store the ciphertext (blob) and the iv (char) in the database, and the password and salts would be supplied to the client application by the user or in the application's configuration files?
JeeBee
In that case, I'd store the ciphertext in one field, the IV in another, and the "salt" and "iterations" together in a third. I'd prompt the user in the client application for the password, and derive the key using the stored salt and iterations. Then initialize the cipher with the derived key and stored IV, and decrypt the content.
erickson
@erickson: in case you store iv, salt, etc. in the database, why not just use 'PBEWithMD5AndDES' and append the salt to the encrypted text, after loading u can strip the salt and use it for decryption. This way PBE is implemented in jasypt framework: www.jasypt.org
Chris
First, that would be DES encryption, not AES. Most providers don't have good support for the `PBEwith<prf>and<encryption>` algorithms; for example, the SunJCE doesn't provide and PBE for AES. Second, enabling jasypt is a non-goal. A package that purports to offer security without requiring an understanding of the underlying principles seems dangerous prima facie.
erickson
@erickson so the lack of support is the only criteria not to use 'PBEWithMD5AndDES'? Are there any further criterias not to use this algo for enryption of data stored in a db?
Chris
Although MD5 is "broken" in some applications, I don't think that it is a problem here. But the weakness of DES is definitely a problem. The tiny key of DES can be broken in hours or days using a few thousand dollars worth of equipment.
erickson
A: 

Maybe you should try the BouncyCastle crypto provider. It is free and you can use larger key sizes than the default JDK.

kd304
A: 

i tried this and it works in one system. when i am trying to run in another system it gives error: algorithm aes not found

saran