I have a strange issue trying to match decryption between an existing iOS app, a .net server, and and Android app that I'm working on. I've checked that my program outputs byte for byte the same encryption as the iOS and decrypts it's own packets perfectly. It appears that the server is able to decrypt the packets sent from the Android app, but when I try to decode the packets from the server I'm getting a BadPaddingException on the Android, whereas the iOS version decodes properly. I've also checked that the Key and IV are byte identical.
edit: I've added the server side code (part of a UDP socket listener) from my client, at first glance it looks like padding has not been defined properly, but my research says the the default is PKCS7, so I'm still confused as to what's causing the problem.
I've tested message lengths (coming from the server) before and after decryption and I see 2 different messages. one is a null keep alive message of 16 bytes before decryption, 0 bytes after decryption. The second message is 128 bytes before decryption and 112 bytes after decryption, in iOS. Both fail to decrypt in Android.
iOS:
+ (NSData*)decryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv;
{
int FBENCRYPT_BLOCK_SIZE = kCCBlockSizeAES128;
int FBENCRYPT_KEY_SIZE = kCCKeySizeAES256;
// setup key
unsigned char cKey[FBENCRYPT_KEY_SIZE];
bzero(cKey, sizeof(cKey));
[key getBytes:cKey length:FBENCRYPT_KEY_SIZE];
// setup iv
char cIv[FBENCRYPT_BLOCK_SIZE];
bzero(cIv, FBENCRYPT_BLOCK_SIZE);
if (iv) {
[iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE];
}
NSData* Result = nil;
// setup output buffer
size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
void *buffer = malloc(bufferSize);
// do decrypt
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
cKey,
kCCKeySizeAES256,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&decryptedSize);
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
} else {
free(buffer);
NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
}
return result;
}
Android:
byte[] decryptData(byte[] data, byte[] key, byte[] iv)
{
static int FBENCRYPT_BLOCK_SIZE = 16; //(kCCBlockSizeAES128)
static int FBENCRYPT_KEY_SIZE = 32; //(kCCKeySizeAES256)
// setup key
byte[] cKey = new byte[FBENCRYPT_KEY_SIZE];
Arrays.fill(cKey, (byte) 0x00);
int num = FBENCRYPT_KEY_SIZE;
if (key.length<num)
num = key.length;
System.arraycopy(key, 0, cKey, 0, num);
// setup iv
byte[] cIv = new byte[FBENCRYPT_BLOCK_SIZE];
Arrays.fill(cIv, (byte) 0x00);
if (iv!=null) {
System.arraycopy(iv, 0, cIv, 0, iv.length);
}
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec skeySpec = new SecretKeySpec(cKey, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(cIv);
aesCipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
byte[] byteCipherText = aesCipher.doFinal(data);
return byteCipherText;
}
Server C#:
public enum AESBitCounts
{
AES64Bit = 8,
AES128Bit = 16,
AES256Bit = 32
}
public static byte[] Encrypt(byte[] RawPayload, byte[] key, AESBitCounts AESBitCount)
{
Symmetric sym = new Symmetric(Symmetric.Provider.Rijndael, false);
//sym.mcrypto.Padding = System.Security.Cryptography.PaddingMode.None;
sym.IntializationVector = new Data(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
Data deckey = new Data();
deckey.MinBytes = (Int32)AESBitCount;
deckey.MaxBytes = (Int32)AESBitCount;
deckey.Bytes = key;
Byte fred = deckey.Bytes[0];
Data encrypted = sym.Encrypt(new Data(RawPayload), deckey);
return encrypted.Bytes;
}