简体   繁体   English

使用Objective-C加密并使用MCRYPT_RIJNDAEL_256 MCRYPT_MODE_ECB在PHP中解密

[英]Encrypt with Objective-C and decrypt in PHP using MCRYPT_RIJNDAEL_256 MCRYPT_MODE_ECB

First I want to say that I have really tried to solve this by myself and read a lot of stuff (like this Objective-C version of PHP mcrypt_encrypt and this How to Decrypt a PHP Script in Objective-C / ios ) 首先,我想说的是,我确实尝试过自己解决这个问题,并阅读了很多东西(例如,PHP mcrypt_encrypt的这个Objective-C版本以及这个Objective-C / ios中的如何解密PHP脚本

I'm really stuck for hours. 我真的被困了几个小时。 I have to implement a server API in iOS (as does my colleague next to me on Android). 我必须在iOS中实现服务器API(我旁边的同事在Android上也是如此)。 The server people told us we have to send an encrypted password, which they will decrypt with mcrypt_decrypt . 服务器人员告诉我们,我们必须发送一个加密的密码,他们将使用mcrypt_decrypt解密。 They sent us the code they use to test the encryption/ decryption, here is their encryption part: 他们向我们发送了用于测试加密/解密的代码,这是他们的加密部分:

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=

Now we are both trying to implement the encryption, but I will concentrate on the iOS part. 现在我们都在尝试实现加密,但是我将专注于iOS部分。 Here is where I'm now: 这是我现在的位置:

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;

Whatever I do, the result is never the same. 无论我做什么,结果都不会相同。 I came across an answer where someone said, that different results in encoding may be ok, but in this case, the server gives me an error, saying that the password is not right. 我遇到一个回答,有人说,编码的不同结果可能没问题,但是在这种情况下,服务器给我一个错误,说密码不正确。 Which means that the decryption also leads to different results. 这意味着解密还会导致不同的结果。

Does someone see any error in these lines of frustration? 有人在这些挫折中看到任何错误吗?

EDIT: If I set everything to 128, in PHP MCRYPT_RIJNDAEL_256 to MCRYPT_RIJNDAEL_128 and in Objective C kCCKeySizeAES256 to kCCKeySizeAES128, I can encrypt with Objective C and decrypt successfully with my own PHP script. 编辑:如果我将所有内容都设置为128,则在PHP MCRYPT_RIJNDAEL_256为MCRYPT_RIJNDAEL_128和在Objective C kCCKeySizeAES256为kCCKeySizeAES128中,我可以使用Objective C进行加密,并使用自己的PHP脚本成功解密。 In that case the encryptet strings still don't look the same, but they have the same length. 在那种情况下,加密字符串仍然看起来不一样,但是它们的长度相同。 I assume that the padding on the Objective C side, will append bytes to key and password, until they are 16 byte long. 我假设目标C端的填充会将字节附加到密钥和密码上,直到它们长16个字节为止。 But using kCCKeySizeAES256, both values still seem to be appended to 16 bytes, not 32 (speculation!!!). 但是使用kCCKeySizeAES256,这两个值似乎仍附加到16个字节,而不是32个(推测!!!)。 Maybe this is the cause. 也许这就是原因。 I still would be glad for some help! 我仍然很乐意提供帮助!

MCRYPT_RIJNDAEL_256 is not AES . MCRYPT_RIJNDAEL_256 不是AES This algorithm of mcrypt indicates Rijndael with a block size of 256 bits. 该mcrypt算法指示Rijndael的块大小为256位。 The key size is determined by the amount of bytes within the key (it's rounded up to the nearest key size in PHP using right padding with 00 valued bytes, and is cut if it exceeds 256 bits). 密钥大小由密钥中的字节数决定(在PHP中使用00值字节的右填充将其舍入为最接近的密钥大小,如果超过256位,则将其切入)。 Note that PHP uses zero padding. 请注意,PHP使用零填充。 You should however use PKCS#7 padding, there should be few implementations of that out there (eg in the comments of mcrypt_encrypt ). 但是,您应该使用PKCS#7填充,那里应该几乎没有实现(例如,在mcrypt_encrypt的注释中)。

To use AES-256, use MCRYPT_RIJNDAEL_128 with a key of 32 bytes. 要使用AES-256,请使用MCRYPT_RIJNDAEL_128 ,密钥为32个字节。 You won't find many implementations of Rijndael with 256 bit block size. 您不会找到Rijndael具有256位块大小的许多实现。 It does not add much security and it is not standardized (by NIST, anyway). 它不会增加太多安全性,并且也不是标准化的(无论如何是NIST的)。

The usual caveats apply with crypto. 通常的警告适用于加密货币。 If the IV, the key, the plaintext (character) encoding or ciphertext encoding differs by one bit, you may get a rather different output. 如果IV,密钥,明文(字符)编码或密文编码相差一位,则您可能会得到完全不同的输出。 Test each input/output vector explicitly by printing out the hexadecimal notation of the bytes. 通过打印出字节的十六进制表示法显式测试每个输入/输出向量。

In addition, you getCString:maxLength:encoding needs a buffer size one bigger than the string you intend to store, as it will add the NUL byte for you. 另外,您的getCString:maxLength:encoding需要的缓冲区大小比要存储的字符串大一倍,因为它将为您添加NUL字节。 Just put a +1 in the keyPtr and ivPtr declarations. 只需在keyPtr和ivPtr声明中添加+1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM