【问题标题】:RC4 encryption - CommonCrypto (Objective-C) vs PHPRC4 加密 - CommonCrypto (Objective-C) 与 PHP
【发布时间】:2010-02-10 09:34:41
【问题描述】:

我在服务器上有一个使用 RC4 算法 (http://rc4crypt.devhome.org) 加密的 XML 文件

function encrypt ($pwd, $data, $ispwdHex = 0)
    {
        if ($ispwdHex)
            $pwd = @pack('H*', $pwd); // valid input, please!

        $key[] = '';
        $box[] = '';
        $cipher = '';

        $pwd_length = strlen($pwd);
        $data_length = strlen($data);

        for ($i = 0; $i < 256; $i++)
        {
            $key[$i] = ord($pwd[$i % $pwd_length]);
            $box[$i] = $i;
        }
        for ($j = $i = 0; $i < 256; $i++)
        {
            $j = ($j + $box[$i] + $key[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        for ($a = $j = $i = 0; $i < $data_length; $i++)
        {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $k = $box[(($box[$a] + $box[$j]) % 256)];
            $cipher .= chr(ord($data[$i]) ^ $k);
        }
        return $cipher;
    }

这是我用来解密的 Objective-C 代码:

      NSData *dataToDecrypt = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.url.com/fileCrypted.xml"]] returningResponse:nil error:nil];
        const void *vplainText;
        size_t plainTextBufferSize;


            plainTextBufferSize = [dataToDecrypt length];
            vplainText = [dataToDecrypt bytes];


        CCCryptorStatus ccStatus;
        uint8_t *bufferPtr = NULL;
        size_t bufferPtrSize = 0;
        size_t movedBytes = 0;

        bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
        bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
        memset((void *)bufferPtr, 0x0, bufferPtrSize);

        NSString *key = @"mykey";
        //NSString *initVec = @"init Vec";
        const void *vkey = (const void *) [key UTF8String];
        const void *vinitVec = (const void *) [initVec UTF8String];

size_t keyLength = [[key dataUsingEncoding:NSUTF8StringEncoding] length]; 
        ccStatus = CCCrypt(kCCDecrypt,
                           kCCAlgorithmRC4,
                           0,
                           vkey,
                           kCCKeySizeDES,
                           nil,
                           vplainText,
                           plainTextBufferSize,
                           (void *)bufferPtr,
                           bufferPtrSize,
                           &movedBytes);
        if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
        /*else*/ if (ccStatus == kCCParamError) return @"PARAM ERROR";
        else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
        else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
        else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
        else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
        else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED";

        NSString *result = [[ NSString alloc ] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIEncoding];

日志输出:成功,但我的结果不好(我测试了很多编码,但 ASCII 似乎是好的,参见 PHP 函数 ord ...)

我的都是 RC4 实现标准吗?

编辑:在 Objective-C 代码中删除了 IV Edit2:Objective-C KeyLength = 密码数据长度,去掉选项

【问题讨论】:

  • 您的 objectiv-c 代码使用初始化向量密码。我在你的 php 代码中没有看到 IV,只有默认初始化 $box[$i] = $i;
  • 非常感谢,你很好,虽然解密仍然不起作用...我想我遗漏了一些东西,但我真的对加密感到不舒服.. kCCOptionPKCS7Padding 是个好选择吗?我迷路了,但我必须让解密工作..

标签: php iphone objective-c algorithm encryption


【解决方案1】:

如果您不知道自己在密码学领域做什么,那么“自己动手”无疑是灾难的避风港。您不必相信我,请在The Cult of Schneier 上阅读 John Viega,了解试图“推出自己的”密码学的普通程序员。释义:不要这样做。

由于这是一个文件,我猜是一个合理的小文件,您可以使用更多标准和更高级别的库,使用 SSL(OpenSSL 等)或 OpenPGP(GPG 等)等标准来执行必要的操作加密/解密。我相信在 Objective-C(或 iPhone 环境)和 PHP 中都有对 SSL 的库或模块支持。

特别是关于 RC4,它是一种流密码,看似简单,但在实现细节上却很容易搞砸。请参阅The Misuse of RC4 in Microsoft Word and ExcelCan you recommend RC4 128-bit encrypted software? 了解一个著名的历史示例,以及安全/密码学专家(PGP Corp. 的前 CTO 和联合创始人)的推荐。


添加:

php 脚本中的密钥大小基于密码数据的原始长度。它也不使用任何 PKCS7 Padding,所以我认为该字段应该为零 (0)(CCryptor 不支持流密码的填充,php 版本当然不使用它)。在您的代码中,CCCrypt 使用了 8 个字节(64* 位)的密钥大小,而我相信您希望它是密码(二进制数据)的长度(以字节为单位)。

没有MAC 或数据哈希,因此函数将无法从无效解码中确定有效。

我认为这将使您更接近与这种不安全的 RC4 实现(PHP 中的 RC4crypt)的兼容性。

【讨论】:

  • 您好,首先,感谢您抽出宝贵时间为我提供建议,我认为您没问题。但问题是:我别无选择,内容提供者正在用 PHP 中的 RC4 crypt 加密文件,并给我密钥。我不能让他为我更改加密,因为其他服务使用该文件。我认为这不是一个好方法,我通常建议使用带有时间变量的公钥/私钥的 API 系统。所以我知道我在做什么不是好方法。但我必须以这种方式解码 iPhone 上的文件:-/ 一切顺利。
  • 您好 mctylr,感谢您的帮助,我添加了变量 keyLength 并删除了 PKCS7 填充选项。 ------ 对于有效或无效的解码,如果我得到一个有效的 XML,我很确定解码是有效的。 ---- 错误可能来自编码吗?我觉得自己真的很愚蠢...... :(
  • 如果您的意思是可以从数据字符串的文本编码转换中引入错误,那么可以。我不知道 Objective-C,所以我不清楚你使用 UTF-8 字符串 (initVec UTF8String),然后在最后一行 encoding:NSASCIIEncoding。加密和解密将输入和输出都视为二进制数据,因此如果可能,最好使用 C 风格的数组char
  • 顺便说一句,这里有一些测试向量可用于测试两种实现en.wikipedia.org/wiki/RC4#Test_vectors
【解决方案2】:

以@mctylr 为基础,尽可能避免自己滚动。如果您需要 RC4,请使用预构建/测试的库:OpenSSL RC4。您可以用大约 3 行代码替换整个代码。

【讨论】:

    猜你喜欢
    • 2015-02-09
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多