EXC_BAD_ACCESS Код 2 на CCCrypt

Я пытаюсь использовать шифрование DES для шифрования паролей (не спрашивайте, почему DES, я знаю, что это менее безопасно). Я делаю это впервые в iOS, поэтому мне пришлось полагаться на другой пост о том, как это сделать.

Когда я запускаю шифрование, оно возвращает null, то же самое с расшифровкой уже зашифрованной строки (я использовал онлайн-инструмент для шифрования). Когда я поставил точку останова, чтобы посмотреть, что происходит, она остановилась на CCCrypt с упоминанием EXC_BAD_ACCESS (Code 2).

Я пытался использовать разные CCOptions, но всегда возвращал одно и то же. Любой намек, что происходит не так? Требуется ли строка iv?

Я использовал следующую категорию NSString для шифрования или расшифровки строк:

#import "NSString+DES.h"

@implementation NSString(DES)

- (NSString*) encryptDES: (NSString *) key
{
    const void *vplainText;
    size_t plainTextBufferSize;

    plainTextBufferSize = [self length];
    vplainText = (const void *) [self UTF8String];

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

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


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

    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithmDES,
                       kCCOptionPKCS7Padding | kCCOptionECBMode,
                       vkey,
                       kCCKeySizeDES,
                       NULL,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       movedBytes);

    NSString *result;
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    return result;
}

- (NSString *) decryptDES: (NSString *) key
{
    const void *vplainText;
    size_t plainTextBufferSize;

    plainTextBufferSize = [self length];
    vplainText = (const void *) [self UTF8String];

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

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


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

    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithmDES,
                       kCCOptionPKCS7Padding | kCCOptionECBMode,
                       vkey, //"123456789012345678901234", //key
                       kCCKeySizeDES,
                       NULL,// vinitVec, //"init Vec", //iv,
                       vplainText, //"Your Name", //plainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       movedBytes);

    NSString *result;
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    return result;
}

@end

Обновление:

Я проверил еще несколько мест и немного изменил код, шифрование работает, но не расшифровывается с правильным значением.

Например, когда я использую YourName в качестве строки и 12345 в качестве ключа, я получаю Fu2sK61e7l5rkXRhAKjPWA== в качестве зашифрованного кода, но расшифровка возвращает +54qWCYTB5LkdARDZjAow==, а не YourName.

Обновлен код:

#import "NSString+DES.h"

@implementation NSString(DES)

- (NSString*) encryptDES: (NSString *) key
{
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *stringData = [self dataUsingEncoding:NSUTF8StringEncoding];
    size_t numBytesEncrypted = 0;
    size_t bufferSize = stringData.length + kCCBlockSizeDES;
    void *buffer = malloc(bufferSize);

    CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
                                     keyData.bytes, kCCKeySizeDES,
                                     NULL,
                                     stringData.bytes, stringData.length,
                                     buffer, bufferSize,
                                     &numBytesEncrypted);
    NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    free(buffer);
    if( result == kCCSuccess )
    {
        NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        return resultStr;
    } else {
        NSLog(@"Failed DES encrypt...");
        return nil;
    }

}

- (NSString *) decryptDES: (NSString *) key
{
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *stringData = [[NSData alloc] initWithBase64EncodedString:self options:0];

    size_t numBytesEncrypted = 0;
    size_t bufferSize = stringData.length + kCCBlockSizeDES;
    void *buffer = malloc(bufferSize);

    CCCryptorStatus result = CCCrypt( kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
                                     keyData.bytes, kCCKeySizeDES,
                                     NULL,
                                     stringData.bytes, stringData.length,
                                     buffer, bufferSize,
                                     &numBytesEncrypted);
    NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
    free(buffer);
    if( result == kCCSuccess )
    {
        NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        return resultStr;
    } else {
        NSLog(@"Failed DES decrypt...");
        return nil;
    }
}

@end

person noob    schedule 01.05.2015    source источник
comment
@Bhavin 'ccStatus = CCCrypt(...);' тут виноват.   -  person noob    schedule 01.05.2015
comment
хорошо... если бы вы проверили эту ссылку... stackoverflow. com/questions/11717193/exc-плохой-код-доступа-2   -  person EI Captain v2.0    schedule 01.05.2015
comment
Режим ECB не использует iv.   -  person zaph    schedule 01.05.2015
comment
Ключ должен быть точно 8-байтовым для DES, если он короткий, результат будет неопределенным. В обновленном коде ключ имеет длину 5 байтов, но длина указана как 8 байтов (kCCKeySizeDES), поэтому три отсутствующих байта ключа будут любыми байтами, следующими за keyData.   -  person zaph    schedule 01.05.2015
comment
Обратите внимание, что в обновленном ответе вы не указали режим ECB, по умолчанию используется режим CBC. Вам нужно добавить kCCOptionECBMode.   -  person zaph    schedule 01.05.2015
comment
С двумя вышеуказанными изменениями в коде обновления (ключ = 12345679 и режим ECB) он даст тот же результат, что и мой ответ.   -  person zaph    schedule 01.05.2015
comment
@Zaph Спасибо за комментарии. Это фактически решает часть шифрования как в коде. Но расшифровка не работает. Я получаю 9Bo4VzSXN4CePfTX2pdtVnrwJIR6plUR в первом коде, получая WW91ciBOYW1l во втором коде после расшифровки. Я предполагаю, что это связано с декодированием base64.   -  person noob    schedule 01.05.2015
comment
При расшифровке вы не хотите кодировать Base64, вы хотите преобразовать данные в NSString: NSString * resultStr = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding];   -  person zaph    schedule 01.05.2015
comment
Примечание. Если вы используете онлайн-шифрование, использующее функцию php mcrypt, последний блок данных будет неверным, поскольку mcrypt не поддерживает заполнение PKCS#7, оно использует нестандартное и небезопасное заполнение нулями.   -  person zaph    schedule 02.05.2015
comment
@Zaph Большое спасибо за вашу помощь. Расшифровка работает во втором методе, но не в первом. Первый возвращает нулевую строку. Но мне этого достаточно. Во-вторых, можете ли вы также опубликовать эти комментарии в своем ответе? Это помогло бы и другим.   -  person noob    schedule 02.05.2015


Ответы (1)


Кажется, существует общая путаница в отношении алгоритма, DES или 3DES, используется смесь, но ключ - 3DES (24 байта). Ключ нужно изменить на 8-байтовый. Константа размера блока также должна быть изменена на kCCBlockSizeDES, но это не вызовет ошибки, поскольку это то же значение.

Для метода:

- (NSString *) decryptDES: (NSString *) key

Ошибка неправильного доступа вызвана тем, что для movedBytes не выделена память, а только указатель. Измените объявление на:

size_t movedBytes;

Измените ссылку на movedBytes в CCCrypt на &movedBytes.

Тестовый вывод для шифрования:

строка: Ваше имя
ключ: 12345678

moveBytes: 16
myData: 136142f6 6cd98e01 af1eef46 28d36499
результат: E2FC9mzZjgGvHu9GKNNkmQ==

Примечания из комментариев по запросу:

Режим ECB не использует iv.

Ключ должен быть точно 8-байтовым для DES, если он короткий, результат будет неопределенным. В обновленном коде ключ имеет длину 5 байтов, но длина указана как 8 байтов (kCCKeySizeDES), поэтому три отсутствующих байта ключа будут любыми байтами, следующими за keyData.

В обновленном ответе не указан режим ECB, по умолчанию используется режим CBC. Добавьте kCCOptionECBMode.

При расшифровке не используйте кодировку Base64, преобразуйте данные в NSString:

NSString * resultStr = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding];  

При использовании онлайн-шифрования, в котором используется функция php mcrypt, последний блок данных будет неверным, поскольку mcrypt не поддерживает заполнение PKCS#7, оно использует нестандартное и небезопасное заполнение нулями.

person zaph    schedule 01.05.2015
comment
Спасибо за ответ. Однако мне нужен алгоритм DES только потому, что уже есть некоторые зашифрованные данные, которые мне тоже нужно расшифровать. Кроме того, я проверил результат с помощью онлайн-инструментов, и он, похоже, не совпадает. Я использую этот инструмент — codebeautify.org/encrypt-decrypt. - person noob; 01.05.2015