Шифрование RC4 - CommonCrypto (Objective-C) против PHP - PullRequest
0 голосов
/ 10 февраля 2010

У меня есть файл XML на сервере, зашифрованный с помощью алгоритма RC4 (http://rc4crypt.devhome.org)

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;
    }

Вот код объективного 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?

Редактировать: удален IV в коде Objective-C Edit2: Objective-C KeyLength = длина данных пароля, удаленная опция

Ответы [ 2 ]

3 голосов
/ 10 февраля 2010

Если вы не знаете, что делаете в криптографии, то «самообслуживание» - верный пожарный сигнал к катастрофе. Вы не должны мне верить, прочитайте Джона Вьегу на The Cult of Schneier о программистах общего профиля, которые пытаются «раскрутить свою» криптографию. Перефразировано: Не делай этого.

Поскольку это файл, и я предполагаю, что достаточно небольшой файл, вы можете использовать больше стандартных библиотек и библиотек более высокого уровня, используя такие стандарты, как SSL (OpenSSL и др.) Или OpenPGP (GPG и т. Д.) Для выполнения необходимых действий. шифрование / дешифрование. Я полагаю, что библиотека или модуль поддерживают SSL как в Objective-C (или в среде iPhone), так и в PHP.

В частности, в отношении RC4, это потоковый шифр, который обманчиво прост в написании, но невероятно прост в деталях его реализации. См. Неправильное использование RC4 в Microsoft Word и Excel и Можете ли вы порекомендовать RC4 128-битное зашифрованное программное обеспечение? для известного исторического примера и рекомендации эксперта по безопасности / криптографии ( бывший технический директор и соучредитель PGP Corp.).


Добавлено:

Размер ключа в скрипте php основан на необработанной длине данных пароля. Он также не использует заполнение PKCS7, поэтому я считаю, что поле должно быть равно нулю (0) (CCryptor не поддерживает заполнение потоковых шифров, и версия php, конечно, не использует его). В вашем коде CCCrypt использовал размер ключа 8 байтов (64 * бит), тогда как я считаю, что вы хотите, чтобы он был длиной (в байтах) пароля (двоичные данные).

Нет MAC или хеша данных, поэтому функции не смогут определить действительные из недопустимых декодирований.

Думаю, это приблизит вас к совместимости с этой небезопасной реализацией RC4 (RC4crypt в PHP).

1 голос
/ 17 февраля 2010

Опираясь на @mctylr, старайтесь по возможности не кататься самостоятельно. Если вам нужен RC4, используйте предварительно собранную / протестированную библиотеку: OpenSSL RC4 . Вы можете заменить весь код примерно на 3 строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...