0

I have created a Java file with following code that encrypt or decrypt a string:

public class Aes { public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; IvParameterSpec ivSpec = new IvParameterSpec(iv); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; IvParameterSpec ivSpec = new IvParameterSpec(iv); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } public static String toHex(String txt) { return toHex(txt.getBytes()); } public static String fromHex(String hex) { return new String(toByte(hex)); } public static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } public static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private final static String HEX = "0123456789ABCDEF"; private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } } 

I have success tried encrypt a string, but not to decrypt it back... please help me. This is example code to encrypt that I tested before:

String data = "HELP"; String enc = ""; try { enc = Aes.encrypt("1234567890", data); Log.i("ENCRYPT", data + " TO " + enc); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } 

AND RESULT IS : 48F1880B

My question is, how to decrypt it? I was test using my code above but result not equal to plaintext! please help me...

7
  • 2
    This is the second question that contains this defect getRawKey(..)implementation. Where do you all get this worse code from? Commented Feb 5, 2014 at 15:39
  • I get it from internet, and try to fix it, I just give an example, but I don't found a good example encrypt and decrypt with aes cfb mode, please help me :( Commented Feb 5, 2014 at 15:42
  • I get from this link: stackoverflow.com/questions/11418336/… Commented Feb 5, 2014 at 15:47
  • 2
    The answer from owlstead to that question already indicates that the code is bad - why did you take it anyway? Commented Feb 5, 2014 at 16:21
  • 2
    Sorry to say but it's not possible to write secure code by copy-pasting random code samples from the internet. Commented Feb 5, 2014 at 18:33

2 Answers 2

0

The following example class should give you a good reference of how to encrypt/decrypt properly with all the steps labeled:

public class AES { public static SecretKey generateAESKey(int bits) throws NoSuchAlgorithmException{ //This method is provided as to securely generate a AES key of the given length. //In practice you can specify your own SecureRandom instance. KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(bits); return kgen.generateKey(); } public static byte[] encrypt(SecretKey key, byte[] plaintext) throws Exception{ //In practice you should specify your SecureRandom implementation. SecureRandom rnd = new SecureRandom(); //Generate random IV of 128-bit (AES block size) byte[] IV = new byte[128 / 8]; rnd.nextBytes(IV); IvParameterSpec IVSpec = new IvParameterSpec(IV); //Create the cipher object to perform AES operations. //Specify Advanced Encryption Standard - Cipher Feedback Mode - No Padding Cipher AESCipher = Cipher.getInstance("AES/CFB/NoPadding"); //Initialize the Cipher with the key and initialization vector. AESCipher.init(Cipher.ENCRYPT_MODE, key, IVSpec); //Encrypts the plaintext data byte[] ciphertext = AESCipher.doFinal(plaintext); /* * The IV must now be transferred with the ciphertext somehow. The easiest * way to accomplish this would be to prepend the IV to the ciphertext * message. */ //Allocate new array to hold ciphertext + IV byte[] output = new byte[ciphertext.length + (128 / 8)]; //Copy the respective parts into the array. System.arraycopy(IV, 0, output, 0, IV.length); System.arraycopy(ciphertext, 0, output, IV.length, ciphertext.length); return output; } public static byte[] decrypt(SecretKey key, byte[] IV, byte[] ciphertext) throws Exception{ //Create the cipher object to perform AES operations. //Specify Advanced Encryption Standard - Cipher Feedback Mode - No Padding Cipher AESCipher = Cipher.getInstance("AES/CFB/NoPadding"); //Create the IvParameterSpec object from the raw IV IvParameterSpec IVSpec = new IvParameterSpec(IV); //Initialize the Cipher with the key and initialization vector. AESCipher.init(Cipher.DECRYPT_MODE, key, IVSpec); //Decrypts the ciphertext data byte[] plaintext = AESCipher.doFinal(ciphertext); return plaintext; } public static void main(String[] args) throws Exception{ //Demo the program String sPlaintext = "rainbows"; //String plaintext byte[] rPlaintext = sPlaintext.getBytes(Charset.forName("UTF-8")); //Raw byte array plaintext //We first need to generate a key of 128-bit SecretKey key = generateAESKey(128); //Encrypt the plaintext byte[] output = encrypt(key, rPlaintext); // ----------------- // //Extract the IV from the encryption output byte[] IV = new byte[128 / 8]; byte[] ciphertext = new byte[output.length - (128 / 8)]; System.arraycopy(output, 0, IV, 0, IV.length); System.arraycopy(output, IV.length, ciphertext, 0, ciphertext.length); //Decrypt the ciphertext byte[] dPlaintext = decrypt(key, IV, ciphertext); String decryptedMessage = new String(dPlaintext, Charset.forName("UTF-8")); //Print stuff out System.out.println("Original message: " + sPlaintext); System.out.println("Original message bytes: " + Arrays.toString(rPlaintext)); System.out.println("Encryption Output bytes: " + Arrays.toString(output)); System.out.println("Decrypted message bytes: " + Arrays.toString(dPlaintext)); System.out.println("Decrypted message: " + decryptedMessage); } } 

Few things to note however:

throws Exception 

is not acceptable. This is only placed for the sake of simplifying code and should never be used in practice. Although some of those checked exceptions like NoSuchAlgorithmException is unlikely to be thrown please be wary that the decrypt() method will thrown exceptions for a failed decryption (i.e. bad key/IV/ciphertext).

Leading onto my next point, you should not rely on the decrypt() method throwing exceptions as a way to validate input. This should be one with a secure one-way hash function such as SHA-2.

Note how the key for encryption/decryption is generated once. AES is a symmetrical block cipher which means that the same key is used for both encryption and decryption. Please keep note of that and not generate a new key between encryption and decryption (you can however generate a new key per encryption if you want, as long as you use the same key to decrypt).

Sign up to request clarification or add additional context in comments.

Comments

0

The problem is mainly in

public static String toHex(String txt) { return toHex(txt.getBytes()); } public static String fromHex(String hex) { return new String(toByte(hex)); } public static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; 

while converting String from Hex String you are not converting them with leading zeroes i.e. when ever you are converting a char and the possible value of that char is zero then hex value is also 00 ,by default your method simply ignores the one zero and adds only one zero to the Hex String

Note:- The numerical zero 0 is not equal to the Hex value of Zero.Hex value of zero is a null character, refer the ASCII table.

with leading Zeroes ef1b0030ef without leading zeroes ef1b030ef

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.