Как я создаю Мешанину MD5 последовательности в Какао?

Я знаю, что SHA-1 предпочтен, но этот проект требует, чтобы я использовал MD5.

#include <openssl/md5.h>

- (NSString*) MD5Hasher: (NSString*) query {
    NSData* hashed = [query dataUsingEncoding:NSUTF8StringEncoding];
    unsigned char *digest = MD5([hashed bytes], [hashed length], NULL);
    NSString *final = [NSString stringWithUTF8String: (char *)digest];
    return final;
}

Я получил этот кодекс от ответа до другого подобного вопроса на StackOverflow, но я получаю следующую ошибку от GDB, когда программа ломается в финале возвращения;

(gdb) p digest
$1 = (unsigned char *) 0xa06310e4 "\0206b\260/\336\316^\021\b\a/9\310\225\204"
(gdb) po final
Cannot access memory at address 0x0
(gdb) po digest

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xb0623630
0x98531ed7 in objc_msgSend ()
The program being debugged was signaled while in a function called from GDB.
GDB has restored the context to what it was before the call.
To change this behavior use "set unwindonsignal off"
Evaluation of the expression containing the function
(_NSPrintForDebugger) will be abandoned.

Я не могу иметь никакого смысла его.

40
задан Peter Hosey 7 January 2010 в 06:55
поделиться

5 ответов

Это категория, которую я использую:

NSString+MD5.h

@interface NSString (MD5)

- (NSString *)MD5String;

@end

NSString+MD5.m

#import <CommonCrypto/CommonDigest.h>

@implementation NSString (MD5)

- (NSString *)MD5String {
    const char *cStr = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, (CC_LONG)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]
    ];  
}

@end

Usage

NSString *myString = @"test";
NSString *md5 = [myString MD5String]; // returns NSString of the MD5 of test
111
ответ дан 27 November 2019 в 01:04
поделиться

cdespinosa и irsk уже показали вам вашу реальную проблему, так что позвольте мне просмотреть вашу расшифровку GDB:

(gdb) p digest
$1 = (беззнаковый char *) 0xa06310e4 "\0206b\260/\336\316^\021\b\a/9\310\225\204".

Вы распечатали дайджест в виде C-строки. Здесь видно, что эта строка является необработанными байтами; следовательно, все восьмеричные экранировки (например, \020, \225) и пара знаков препинания (/ и ^). Это не то шестнадцатиричное ASCII представление, которое вы ожидали. Вам повезло, что в нем не было нулевых байт; иначе вы бы не распечатали весь хэш.

(gdb) po final
Невозможно получить доступ к памяти по адресу 0x0

финал равен нулю . Это имеет смысл, так как ваша строка выше не является действительной UTF-8; опять же, это просто байты необработанных данных. stringWithF8String: требует текстовой строки в кодировке UTF-8; вы ее не дали, поэтому она вернула nil.

Для передачи необработанных данных вы бы использовали NSD-данные. В данном случае, я думаю, вам нужно шестнадцатеричное представление, поэтому вам нужно будет создать его самостоятельно, как это показал irsk.

Наконец, подумайте, как вам повезло, что ваш вход не хэшировал действительную строку UTF-8. Если бы он был, вы бы не заметили эту проблему. Возможно, вы захотите построить юнит-тест для этого хэш-метода с помощью этого входа.

(gdb) po digest

Программа получила сигнал EXC_BAD_ACCESS, не смогла получить доступ к памяти.
Причина: KERN_INVALID_ADDRESS по адресу: 0xb0623630
0x98531ed7 в objectc_msgSend()

Ваша программа вышла из строя (конкретная проблема: "плохой доступ", "неправильный адрес") в objc_msgSend. Это связано с тем, что digest либо вообще не является объектом Cocoa/CF, либо был им, но был освобожден. В данном случае, это потому, что дайджест не является объектом какао; это массив байтов C, как показано в вашей строке p-дайджеста выше.

Запомните, что Objective-C - это суперсет из C. Все C в нем существует без изменений. Это означает, что рядом находятся массивы С (например, char []) и NSArrays какао. Более того, поскольку NSArray происходит из структуры Cocoa, а не из языка Objective-C, нет способа сделать объекты NSArray взаимозаменяемыми с массивами С: Вы не можете использовать оператор подписки на массивах Cocoa, и Вы не можете посылать сообщения Objective-C на массивы C.

.
10
ответ дан 27 November 2019 в 01:04
поделиться

Я считаю, что дайджест - это указатель на сырой двоичный хэш. В следующей строке вы пытаетесь интерпретировать его как строку UTF-8, но, скорее всего, он не будет содержать легальных символьных последовательностей в кодировке UTF-8.

Я ожидаю, что вы хотите преобразовать 16-байтовый статический массив беззнакового символа char в 32 шестнадцатеричных символа ASCII [0-9a-f], используя любой алгоритм, который вы сочтете нужным.

3
ответ дан 27 November 2019 в 01:04
поделиться

Функция MD5 не возвращает строку на языке C, она возвращает указатель на некоторые байты. Вы не можете трактовать это как строку.

Если вы хотите создать строку, вам нужно построить строку, используя шестнадцатеричные значения этих байтов. Вот один из способов сделать это как категорию на NSData:

#import <CommonCrypto/CommonDigest.h>
@implementation NSData (MMAdditions)
- (NSString*)md5String
{
    unsigned char md5[CC_MD5_DIGEST_LENGTH];
    CC_MD5([self bytes], [self length], md5);
    return [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            md5[0], md5[1],
            md5[2], md5[3],
            md5[4], md5[5],
            md5[6], md5[7],
            md5[8], md5[9],
            md5[10], md5[11],
            md5[12], md5[13],
            md5[14], md5[15]
            ];
}
@end
3
ответ дан 27 November 2019 в 01:04
поделиться
@implementation NSString (MD5)

+ (NSString *)formattedMD5:(const char *)data length:(unsigned long)len
{
    unsigned char *digest = MD5((unsigned const char *)data, len, NULL);
    NSMutableArray *values = [[NSMutableArray alloc] init];

    for (int i = 0; i < strlen((char *)digest); i++)
    {
        char hexValue[4];
        sprintf(hexValue, "%02X", digest[i]);
        [values addObject:[NSString stringWithCString:hexValue length:strlen(hexValue)]];
    }

    // returns a formatted MD5 fingerprint like
    //      00:00:00:00:00:00:00:00:00
    return [values componentsJoinedByString:@":"];
}

@end
1
ответ дан 27 November 2019 в 01:04
поделиться