首先,我想说我自己真的试图解决这个问题并阅读了很多内容(例如Objective-C version of PHP mcrypt_encrypt和How to Decrypt a PHP Script in Objective-C / ios}
我真的被困了好几个小时。我必须在iOS中实现一个服务器API(就像我在Android上的同事一样)。服务器人告诉我们,我们必须发送加密密码,他们将使用mcrypt_decrypt
解密。他们向我们发送了用于测试加密/解密的代码,这是他们的加密部分:
function fnEncrypt($sValue, $sSecretKey)
{
$ivsize = mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
);
$iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
$encrypted = mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$sSecretKey, $sValue,
MCRYPT_MODE_ECB,
$iv);
$encoded = base64_encode($encrypted);
$trimmed = rtrim($encoded, "\0");
return $trimmed;
}
$prepared = fnEncrypt("somePassword","someKey");
echo $prepared; // => 42bbd9ZPMVFmm7Z9RfLb3zOrCpxnmwhl4gYRSb9WxY8=
现在我们都在尝试实施加密,但我将专注于iOS部分。我现在就在这里:
NSString* key = @"someKey";
NSString* pw = @"somePassword";
NSData *data = [pw dataUsingEncoding:NSUTF8StringEncoding];
char keyPtr[kCCKeySizeAES256];
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSString *iv = @"12345678123456781234567812345678"; // Static
char ivPtr[kCCKeySizeAES256];
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES,
kCCOptionECBMode|kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES256,
ivPtr /* initialization vector (optional) */,
[data bytes],
dataLength, /* input */
buffer,
bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess)
{
NSData* resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
NSString* resultString = [resultData base64EncodedStringWithOptions:0];
NSLog(@"resultString %@", resultString); // => 2rj7sDEoGtwDGPgae1BC1A==
free(buffer);
return resultString;
}
free(buffer);
return nil;
无论我做什么,结果都是不一样的。我遇到了一个答案,有人说,编码的不同结果可能没问题,但在这种情况下,服务器给我一个错误,说密码不对。这意味着解密也会导致不同的结果。
有人在这些挫败感中看到任何错误吗?
编辑: 如果我将所有内容设置为128,在PHP MCRYPT_RIJNDAEL_256到MCRYPT_RIJNDAEL_128,在Objective C kCCKeySizeAES256到kCCKeySizeAES128,我可以使用Objective C加密并使用我自己的PHP脚本成功解密。在这种情况下,加密字符串仍然看起来不一样,但它们具有相同的长度。我假设Objective C端的填充将字节附加到密钥和密码,直到它们长16个字节。但是使用kCCKeySizeAES256,两个值似乎仍然附加到16个字节,而不是32个(推测!!!)。也许这就是原因。我仍然很乐意帮助你!
答案 0 :(得分:2)
MCRYPT_RIJNDAEL_256
不是AES 。该mcrypt算法表示Rijndael的块大小为256位。密钥大小由密钥中的字节数决定(它使用带有00
值字节的右边距填充向上舍入到PHP中最接近的密钥大小,如果超过256位则被削减)。请注意,PHP使用零填充。但是,你应该使用PKCS#7填充,那里的实现应该很少(例如在mcrypt_encrypt
的注释中)。
要使用AES-256,请使用带有32字节密钥的MCRYPT_RIJNDAEL_128
。您不会发现许多具有256位块大小的Rijndael实现。它没有增加太多安全性,也没有标准化(无论如何都是NIST)。
通常的警告适用于加密。如果IV,密钥,明文(字符)编码或密文编码相差一位,则可能会得到相当不同的输出。通过打印出字节的十六进制表示法来明确地测试每个输入/输出向量。
答案 1 :(得分:1)
另外,你得到了CString:maxLength:encoding需要比你想要存储的字符串大一个的缓冲区大小,因为它会为你添加NUL字节。只需在keyPtr和ivPtr声明中输入+1。