Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RNCryptor AES256与PHP MCRYPT_RIJNDAEL_256匹配_Php_Objective C_Encryption_Aes_Rncryptor - Fatal编程技术网

RNCryptor AES256与PHP MCRYPT_RIJNDAEL_256匹配

RNCryptor AES256与PHP MCRYPT_RIJNDAEL_256匹配,php,objective-c,encryption,aes,rncryptor,Php,Objective C,Encryption,Aes,Rncryptor,我在iOS应用程序中调用的PHP API要求以某种定制的方式对负载进行加密。我很难在Objective-C中使用RNCryptor复制这种方法 以下是用于加密字符串的PHP代码: function encrypt($string) { $key = 'some-random-key'; return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(

我在iOS应用程序中调用的PHP API要求以某种定制的方式对负载进行加密。我很难在Objective-C中使用RNCryptor复制这种方法

以下是用于加密字符串的PHP代码:

function encrypt($string) {
    $key = 'some-random-key';
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));
}
这就是我如何在Objective-C中实现相同的加密结果:

+ (NSData*)encryptData:(NSData*)sourceData {

    NSString *keyString = @"some-random-key";
    NSData *key = [[keyString MD5String] dataUsingEncoding:NSUTF8StringEncoding];
    NSData *iv = [[[keyString MD5String] MD5String] dataUsingEncoding:NSUTF8StringEncoding];

    NSMutableData *encryptedData = [NSMutableData data];

    RNCryptorEngine *cryptor = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt settings:kRNCryptorAES256Settings key:key IV:iv error:nil];

    [encryptedData appendData:[cryptor addData:sourceData error:nil]];
    [encryptedData appendData:[cryptor finishWithError:nil]];

    return encryptedData;

}
但这两个函数的结果永远不匹配。例如,对于同一个单字字符串,PHP代码返回
J39gRcuBEaqMIPP1VlizdA8tRjmyAB6za4zG5wcOB/8=
,而在Objective-C中(在结果NSData上运行
base64EncodedStringWithOptions:
后),我得到
1FGpZpVm2p4z3BBY6KW2fw=

我是否需要在RNCryptor设置中进一步调整以使其工作

更新

我直接使用了本机iOS CommonCrypto框架,而没有使用第三方RNCryptor库。我得到的结果和RNCryptor一样。我甚至尝试在Objective-C和PHP代码段中实现AES128,但即使这样,也无法使两个环境的结果匹配

更新2

我使用的
MD5String
方法是NSString上的一个类别,定义如下:

- (NSString *)MD5String {
    const char *cstr = [self UTF8String];
    unsigned char result[16];
    CC_MD5(cstr, strlen(cstr), result);

    return [[NSString stringWithFormat:
            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ] lowercaseString];
}

在脚本语言以外的语言中,
md5
作为十六进制ascii返回是不常见的,甚至
php
提供了二进制输出选项

关于php
mcrypt\u encrypt
,有一些关于标准的东西:

  • 如果密钥小于所需的密钥大小,则使用\0填充该密钥
  • 数据将用\0个字符填充到块的倍数 大小,通常使用填充,例如
    pkcs7
  • 未指定是如何处理非块大小的iv,可以猜测是这样的 也用尾随的\0字符填充
  • 其中,由于
    md5
    方法的十六进制ascii输出,iv将是正确的长度。但是,这会留下数据长度和非标准的填充

    密钥将为32字节,因此在php中将填充32\0个字符。这就引出了将AES256与128位密钥一起使用的问题

    从基础CommonCrypto“CommonCryptor.h”中:

    keyLength:关键材质的长度。必须适用于 选择操作和算法

    密钥长度不正确

    要做的事情:
    1.处理数据长度/填充
    2.处理键的长度

    如需进一步帮助,请提供您正在使用的示例数据以及base64编码之前的十六进制ascii输出
    mcrypt_encrypt

    有关参考信息,请参见:

    而且

    尽管大多数答案都集中在MD5哈希上,但最有可能引起问题的是MCRYPT_RIJNDAEL_256不是AES。它不指定256的密钥大小,而是指定256的块大小,而AES的块大小始终为128位。至于其他参数,在两边的加密程序之前,用十六进制打印出它们的值,以找出它们的值。

    Zaph的注释是

    数据将用\0个字符填充到块大小的倍数

    让我走上正轨,帮助我解决部分问题

    基本上,PHP的
    mcrypt
    只对数据使用
    \0
    填充,而Apple的CommonCryptor允许您在PKCS7填充(
    kCCOptionPKCS7Padding
    )或无填充之间进行选择。这就是我无法让数据匹配的原因之一:在加密之前,数据的填充方式总是不同的

    解决方案是让PHP在运行
    mcrypt
    ()之前对数据执行PKCS7填充,或者让Objective-C执行PHP风格的
    \0
    填充,并确保删除
    kCCOptionPKCS7Padding
    (将NULL传递给CCCrypt选项):


    我知道我来晚了,你可能已经离开了。但我想指出的是,现在有一种RNCryptor,它是ByTestStream与Objective-C实现兼容的。去年夏天,我自己贡献了它,目前我正在维护它。:-)


    所以现在用RNCryptor PHP加密和用RNCryptor Objective-C解密应该很容易,反之亦然。查看详细信息和子项目列表。

    什么是
    MD5String
    方法?它的参数和返回类型是什么?
    NSMutableData *dataToEncrypt = [sourceData mutableCopy];
    NSUInteger dataLength = [dataToEncrypt length];
    
    // See how much padding is required
    NSUInteger padding = kCCBlockSizeAES128 - (dataLength % kCCBlockSizeAES128);
    
    // Add that many \0’s (there could be a more efficient way to do this)
    for (int i=0; i<padding; i++)
        [dataToEncrypt appendData:[@"\0" dataUsingEncoding:NSASCIIStringEncoding]];
    
    // Recalculate the data length
    dataLength = dataToEncrypt.length;
    
    - (NSString*)encryptedBase64String {
    
        // Prepare the data
    
        NSMutableData *sourceData = [[self dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
    
        // Process the key
    
        NSString *key = [[kHSEncryptionKey MD5String] substringWithRange:NSMakeRange(0, 16)];
    
        char keyPtr[kCCKeySizeAES128 + 1];
        bzero(keyPtr, sizeof(keyPtr));
        [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
        // Process the iv
    
        NSString *iv = [[[kHSEncryptionKey MD5String] MD5String] substringWithRange:NSMakeRange(0, 16)];
    
        char ivPtr[kCCKeySizeAES128 + 1];
        bzero(ivPtr, sizeof(ivPtr));
        [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    
        // Pad the data, PHP style
    
        NSUInteger dataLength = [sourceData length];
        NSUInteger padding = kCCBlockSizeAES128 - (dataLength % kCCBlockSizeAES128);
    
        for (int i=0; i<padding; i++)
            [sourceData appendData:[@"\0" dataUsingEncoding:NSASCIIStringEncoding]];
    
        dataLength = sourceData.length;
    
        // Buffer for the resulting data
    
        size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void* buffer = malloc(bufferSize);
    
        // Run the encryption
    
        size_t numBytesEncrypted = 0;
        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, NULL,
                                              keyPtr, kCCKeySizeAES128,
                                              ivPtr,
                                              sourceData.bytes, dataLength, /* input */
                                              buffer, bufferSize, /* output */
                                              &numBytesEncrypted);
    
        if (cryptStatus == kCCSuccess) {
            NSData *encyptedData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
            return [encyptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        }
    
        free(buffer);
        return nil;
    }