Reputation: 2565
I'm working on a android project in which I have to decrypt string from a file in PHP server, encryption was done using PHP.(AES 128 algorithm)
Encryption Code:
function aes128Encrypt($key, $data) {
$key = md5($key);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}
My code for getting string from URL:
String myUri = "http://www.example.com/lib2.php";
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(myUri);
HttpResponse response = httpClient.execute(get);
String bodyHtml = "";
String xmlFile = "";
bodyHtml = EntityUtils.toString(response.getEntity());
System.out.println(bodyHtml);
xmlFile = decrypt(bodyHtml);
System.out.println(xmlFile);
decrypt() method:
public static String decrypt(String encData) throws Exception
{
Key key = generateKey();
Cipher c = Cipher.getInstance(algo + "/CBC/PKCS7Padding");
//Cipher c = Cipher.getInstance(algo);
IvParameterSpec ivSpec = new IvParameterSpec(ivbytes);
c.init(Cipher.DECRYPT_MODE, key , ivSpec);
//byte[] decValue = Base64.decode(encData , Base64.NO_PADDING);
//byte[] decFin = Base64.decode(decValue, Base64.NO_PADDING);
//byte[] decFinal = c.doFinal(decValue);
byte[] decFinal = c.doFinal(encData.getBytes());
String getAns = new String(decFinal, "UTF8");
return getAns;
}
In generateKey():
public static Key generateKey()
{
try {
MessageDigest digest = java.security.MessageDigest
.getInstance("MD5");
digest.update(myChar.getBytes());
key1 = digest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
Key key = new SecretKeySpec(key1,algo);
return key;
}
}
The Logcat shows below exception:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
at the line c.doFinal()
The Codes I'v commented out are also the codes I'v used to check. What is wrong with this code?. Any help will be appreciated.
Upvotes: 1
Views: 10649
Reputation: 1
I solved my problem by avoiding reuse of cipher. each time i init it again. just initing might be enough.
try {
SecretKeyFactory factory = SecretKeyFactory
.getInstance(SECRET_KEY_ALGORITHM);
KeySpec spec = new PBEKeySpec(ps, salt, ITERATIONS, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);
// Build encryptor and get IV
ecipher = Cipher.getInstance(TRANSFORMATION);
ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
// Build decryptor
dcipher = Cipher.getInstance(TRANSFORMATION);
dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
} catch (Exception e) {
e.printStackTrace();
}
Upvotes: 0
Reputation: 93978
The problem probably is the way you treat the value from the PHP server as a Java String
. The PHP mcrypt_encrypt
function returns a binary string, where each byte can have any value. PHP mcrypt_encrypt
does not use any character encoding. So using EntityUtils.toString()
is already an error - and using String.getBytes()
without specifying the encoding generally is as well.
You just need to use either getContent()
or writeTo(OutputStream outstream)
to get the the binary ciphertext. If you opt for the first option, you can wrap a CipherInputStream
around it. Initialize it with the "AES/CBC/NoPadding"
cipher and you can directly decrypt the plain text string. Beware that you may have to trim a certain number of 00
valued bytes from the result to get to the plaintext.
Upvotes: 1
Reputation: 178
Your chiper is expecting padding "/CBC/PKCS7Padding". This has nothing to do with encoding of messages (BASE64). Either change expected chipher on java side or encrypt with padding on php side.
Chipers are specified algorithm/mode/padding
or algortihm
, see http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html for details.
Your are specifying a chiper with padding but actually do zero padding on php side,
excerpt from http://www.php.net/manual/de/function.mcrypt-encrypt.php:
# creates a cipher text compatible with AES (Rijndael block size = 128)
# to keep the text confidential
# only suitable for encoded input that never ends with value 00h
# (because of default zero padding)
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
$plaintext, MCRYPT_MODE_CBC, $iv);
Upvotes: 2