这是一个令人头疼的问题。而且它涉及加密使得它特别粗糙!
我有Objective-C代码,它使用CCCrypt到AES 128加密iPhone上的消息,我使用Protocol Buffers和AsyncSockets发送。 iOS代码如下:
- (NSData *)AES128EncryptWithKey:(const char *)keyPtr {
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128, // oorspronkelijk 256
keyPtr /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
} else {
free(buffer); //free the buffer;
return nil;
}
}
我按如下方式定义AES托管对象:
AesManaged AES = new AesManaged();
AES.Padding = PaddingMode.PKCS7;
var shared = /* a shared key */
var salt = shared + DH.P;
Rfc2898DeriveBytes deriveBytes = /* derived bytes from shared */
byte[] ekey = deriveBytes.GetBytes(16);
byte[] eiv = ekey;
AES.Key = ekey;
AES.IV = eiv;
然后我使用以下C#.Net代码在我的服务器上解密这些数据:
public byte[] Decrypt(byte[] encryptedData)
{
byte[] dec = null;
MemoryStream ms = new MemoryStream(encryptedData);
using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Read))
{
BinaryReader reader = new BinaryReader(cs);
dec = reader.ReadBytes(encryptedData.Length);
reader.Close();
}
return dec;
}
当我在iOS模拟器中运行以及从Xcode调试到设备本身时,这非常有效。但是,当我创建应用程序的分发包(IPA文件)并将其部署到设备时,我在服务器上得到此异常:
System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
我发送的数据导致它的未加密数据长度为4,这会产生16的加密大小。由于我认为这是AES块大小,这似乎是正确的。调试日志显示这是已部署的应用程序和模拟器上的消息大小。所以尺寸似乎没有错。
阅读有关此异常的信息表明,填充的创建方式有问题。但是为什么部署时设备与通过调试器或模拟器运行时有所不同?
提前致谢。我一直试图解决这个问题几天,这让我无法通过Apple测试我的应用程序。
答案 0 :(得分:0)
几点说明:
a)您能否在iOS上显示从共享密钥派生加密密钥的代码。
你为.NET展示了这段代码,但没有为iOS展示。
b)确保iOS上的keyPtr实际上包含128位(16字节)。如果由于任何原因它包含较少,您可能会遇到此问题
c)我不建议将keyPtr作为IV传递。一般来说这是一种不好的做法。您应该为每个加密文件创建新的唯一IV。
出于测试目的,您可以将其设置为NULL(要担心一个较少的变量)。
d)是否可以显示导出加密密钥的整个.NET代码。 有几件事情不明确:
什么是DH.P?
Rfc2898DeriveBytes deriveBytes = / *来自共享* / *的派生字节 据我所知,应该有类似新的Rfc2898DeriveBytes(pwd,salt);并且你用什么作为pwd和盐并不明显。