Reputation: 1300
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
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
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
Reputation: 1502835
There are three separate transformations here:
... 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