Monzer Yaghi
Monzer Yaghi

Reputation: 1300

Java AES not decrypting Arabic

I'm working on Eclipse to encrypt and decrypt a string. I'm using the following functions:

private final static String ALGORITHM = "AES";


    public static String cipher(String secretKey, String data) throws Exception {



        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), secretKey.getBytes(), 128, 256);

        SecretKey tmp = factory.generateSecret(spec);

        SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);



        Cipher cipher = Cipher.getInstance(ALGORITHM);

        cipher.init(Cipher.ENCRYPT_MODE, key);



        return toHex(cipher.doFinal(data.getBytes()));

    }


    public static String decipher(String secretKey, String data) throws Exception {



        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), secretKey.getBytes(), 128, 256);

        SecretKey tmp = factory.generateSecret(spec);

        SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);



        Cipher cipher = Cipher.getInstance(ALGORITHM);



        cipher.init(Cipher.DECRYPT_MODE, key);



        return new String(cipher.doFinal(toByte(data)));

    }


    private 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[] stringBytes) {

        StringBuffer result = new StringBuffer(2*stringBytes.length);



        for (int i = 0; i < stringBytes.length; i++) {

            result.append(HEX.charAt((stringBytes[i]>>4)&0x0f)).append(HEX.charAt(stringBytes[i]&0x0f));

        }



        return result.toString();

    }
    private final static String HEX = "0123456789ABCDEF";

The string that I'm working on contains English and Arabic characters. When I'm decrypting the string, the arabic characters are replaced by a question mark ( ? )

How can I solve this problem ?

Upvotes: 3

Views: 947

Answers (3)

Mark Rotteveel
Mark Rotteveel

Reputation: 109144

The problem is that you use data.getBytes() (and secretKey.getBytes()). This method uses the default encoding on your OS. For example in Western Europe on Windows this default is Cp1252 which doesn't contain Arabic, and therefor converts unsupported characters to ?.

You will need to use data.getBytes("UTF-8) and the same also when you create the String.

Bottomline: always be explicit with your character set!

Upvotes: 5

Monzer Yaghi
Monzer Yaghi

Reputation: 1300

Well I made two adjustments and it worked :

  • In the cipher function I wrote this : return toHex(cipher.doFinal(data.getBytes("UTF-8")));

  • In the decipher function I wrote this : return new String(cipher.doFinal(toByte(data)),"UTF-8");

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502835

There are three separate transformations here:

  • Unencrypted text to unencrypted bytes
  • Unencrypted bytes to encrypted bytes
  • Encrypted bytes to hex

... and the reverse, of course.

I suspect the problem is in the first step. Currently you're using new String(byte[]) and String.getBytes(), both of which use the platform default encoding. That's almost always a bad idea. It's generally a good idea to use UTF-8 (e.g. using StandardCharsets.UTF_8) for all encoding and decoding, unless you have a good reason to use something else.

That's one starting point - but another is to look at each of those transformations separately, and work out where the data is being broken. Lots of diagnostics will help here.

I have a blog post about precisely this sort of problem, which goes into more detail.

Upvotes: 3

Related Questions