Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java AES and using my own Key

Tags:

java

key

aes

I want to encrypt a string using AES with my own key. But I'm having trouble with the bit length of the key. Can you review my code and see what I need to fix/change.

public static void main(String[] args) throws Exception {     String username = "[email protected]";     String password = "Password1";     String secretID = "BlahBlahBlah";     String SALT2 = "deliciously salty";      // Get the Key     byte[] key = (SALT2 + username + password).getBytes();     System.out.println((SALT2 + username + password).getBytes().length);      // Need to pad key for AES     // TODO: Best way?      // Generate the secret key specs.     SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");      // Instantiate the cipher     Cipher cipher = Cipher.getInstance("AES");     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);      byte[] encrypted = cipher.doFinal((secrectID).getBytes());     System.out.println("encrypted string: " + asHex(encrypted));      cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);     byte[] original = cipher.doFinal(encrypted);     String originalString = new String(original);     System.out.println("Original string: " + originalString + "\nOriginal string (Hex): " + asHex(original)); } 

Right now I get an exception "Invalid AES key length: 86 bytes". Do I need to pad my key? How should I do it?

Also do I need to set anything for ECB or CBC?

Thanks

like image 403
Bernie Perez Avatar asked Aug 10 '10 17:08

Bernie Perez


People also ask

Does AES use public and private keys?

AES is a symmetric algorithm, so it does not have public and private keys - only a shared secret. Show activity on this post. In the simplest form: AES is a symetric algorithm, it uses the same key for encryption and decryption.So tat whoever has the key can read your message.

Does AES use a key?

AES uses symmetric key encryption, which involves the use of only one secret key to cipher and decipher information.

What is secret key in AES?

AES-256 Secret Key The secret key used in AES-256 must be 256 bits long. In order to use a password or passphrase as the key, a hashing algorithm needs to be used to extend the length.


2 Answers

Edit:

As written in the comments the old code is not "best practice". You should use a keygeneration algorithm like PBKDF2 with a high iteration count. You also should use at least partly a non static (meaning for each "identity" exclusive) salt. If possible randomly generated and stored together with the ciphertext.

    SecureRandom sr = SecureRandom.getInstanceStrong();     byte[] salt = new byte[16];     sr.nextBytes(salt);      PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1000, 128 * 8);     SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);     Cipher aes = Cipher.getInstance("AES");     aes.init(Cipher.ENCRYPT_MODE, key); 

===========

Old Answer

You should use SHA-1 to generate a hash from your key and trim the result to 128 bit (16 bytes).

Additionally don't generate byte arrays from Strings through getBytes() it uses the platform default Charset. So the password "blaöä" results in different byte array on different platforms.

byte[] key = (SALT2 + username + password).getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit  SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 

Edit: If you need 256 bit as key sizes you need to download the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" Oracle download link, use SHA-256 as hash and remove the Arrays.copyOf line. "ECB" is the default Cipher Mode and "PKCS5Padding" the default padding. You could use different Cipher Modes and Padding Modes through the Cipher.getInstance string using following format: "Cipher/Mode/Padding"

For AES using CTS and PKCS5Padding the string is: "AES/CTS/PKCS5Padding"

like image 101
mknjc Avatar answered Sep 30 '22 08:09

mknjc


You should use a KeyGenerator to generate the Key,

AES key lengths are 128, 192, and 256 bit depending on the cipher you want to use.

Take a look at the tutorial here

Here is the code for Password Based Encryption, this has the password being entered through System.in you can change that to use a stored password if you want.

        PBEKeySpec pbeKeySpec;         PBEParameterSpec pbeParamSpec;         SecretKeyFactory keyFac;          // Salt         byte[] salt = {             (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,             (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99         };          // Iteration count         int count = 20;          // Create PBE parameter set         pbeParamSpec = new PBEParameterSpec(salt, count);          // Prompt user for encryption password.         // Collect user password as char array (using the         // "readPassword" method from above), and convert         // it into a SecretKey object, using a PBE key         // factory.         System.out.print("Enter encryption password:  ");         System.out.flush();         pbeKeySpec = new PBEKeySpec(readPassword(System.in));         keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");         SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);          // Create PBE Cipher         Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");          // Initialize PBE Cipher with key and parameters         pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);          // Our cleartext         byte[] cleartext = "This is another example".getBytes();          // Encrypt the cleartext         byte[] ciphertext = pbeCipher.doFinal(cleartext); 
like image 30
Keibosh Avatar answered Sep 30 '22 08:09

Keibosh