我有一个奇怪的问题,试图匹配现有的iOS应用程序,.net服务器和我正在处理的Android应用程序之间的解密。我已经检查过我的程序输出字节的字节与iOS的加密方式相同,并且完全解密了它自己的数据包。似乎服务器能够解密从Android应用程序发送的数据包,但是当我尝试解码来自服务器的数据包时,我在Android上获得BadPaddingException,而iOS版本正确解码。我还检查过Key和IV是字节相同的。
编辑:我已经从我的客户端添加了服务器端代码(UDP套接字侦听器的一部分),乍一看它似乎没有正确定义填充,但我的研究表明默认是PKCS7,所以我仍然对导致问题的原因感到困惑。
我在解密之前和之后测试了消息长度(来自服务器),我看到了2条不同的消息。一个是解密前16字节的空保持消息,解密后的0字节。在iOS中,第二条消息在解密前为128字节,在解密后为112字节。两者都无法在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;
}
机器人:
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;
}
服务器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;
}
答案 0 :(得分:1)
事实证明,CCCrypt和Cipher之间存在一个重要区别,CCCrypt将返回它能够解密的任何数据,而Cipher一旦得到填充错误,就不会返回任何数据。似乎我的客户端的服务器端脚本正在破坏填充块,以便任何短于16字节的消息在iOS上被解密为null,并且在主消息的情况下只是丢弃填充块。我能够通过在解码之前切断最后16个字节来复制iOS代码的结果,如果没有剩余字节则返回null,并且从使用Cipher.doFinal切换到Cipher.update,这不会期望最终填充阻止出席。
编辑:我实际上并不需要消除最后16个字节。只需从doFinal切换到更新即可。