Reputation: 747
I have a problem related to AES decryption on my server side. When encrypting data in the android client and sending it to the WCF server, the server always return an exception like
System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed. at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count) at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at WindowsFormsApplication1.Form1.Decrypt(Byte[] p_EncryptedMsg, Byte[] p_key, Byte[] p_iv) in c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 76 at WindowsFormsApplication1.Form1.button1_Click(Object sender, EventArgs e) in c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 94}
my android encryption is
public static String enc(String message) {
byte[] keyInBytes = KEY.getBytes();
byte[] encryptedData = null;
KeyGenerator kgen;
try {
kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(keyInBytes);
kgen.init(256, secureRandom);
SecretKey skey = kgen.generateKey();
key = skey.getEncoded();
try {
encryptedData = encrypt(key, message.getBytes());
Log.w("ENC ", new String(encryptedData));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Base64.encodeToString(encryptedData, Base64.DEFAULT);
// return message;
}
private static byte[] encrypt(byte[] raw, byte[] testMessage)
throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, /* "PBEWithSHA1And128BitAES-CBC-BC" */
"AES");
final byte[] iv = KEY.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(testMessage);
try {
decrypt(raw, encrypted);
} catch (Exception e) {
e.getMessage();
// TODO: handle exception
}
return encrypted;
}
and my C# code is
public String Decrypt(byte[] p_EncryptedMsg, byte[] p_key, byte[] p_iv)
{
m_key = new byte[32];
m_iv = new byte[16];
Array.Clear(m_key, 0, 32);
Array.Clear(m_iv, 0, 16);
Array.Copy(p_key, m_key, p_key.Length > 32 ? 32 : p_key.Length);
Array.Copy(p_iv, m_iv, p_iv.Length > 16 ? 16 : p_iv.Length);
if (m_key == null || m_iv == null)
throw new ArgumentNullException("Key or IV is equal to null");
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = m_key;
aesProvider.IV = m_iv;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
decStream.Write(p_EncryptedMsg, 0, p_EncryptedMsg.Length);
decStream.FlushFinalBlock();
String res = System.Text.Encoding.Default.GetString(memStream.ToArray());
return res;
}
}
}
NOTE: I can encrypt and decrypt the text again correctly in the android side.
Upvotes: 0
Views: 2465
Reputation: 747
i found that the problem happened as a result of using SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
as the server side take only the keyInBytes from me not the randomized one, so he can't generate the correct decryption key.
C# code example
using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
{
aesCryptoServiceProvider.Key = key;
aesCryptoServiceProvider.IV = iv;
aesCryptoServiceProvider.Mode = CipherMode.CBC;
aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memoryStream = new MemoryStream())
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(p_EncryptedMsg, 0, encryptedMsg.Length);
cryptoStream.FlushFinalBlock();
return memoryStream.ToArray();
}
}
Upvotes: 0
Reputation: 2586
Well, one problem I see is that your CipherMode on the .Net side should be ECB to match the Java side. Give that a shot and see if that works.
Upvotes: 1