Проблема с HMAC для отправки пароля на сайт

Я пытаюсь создать приложение для своей школы, которое взаимодействует с PowerSchool, программным обеспечением, которое позволяет пользователю просматривать свои оценки, учителей, расписания и многое другое. Я нашел библиотеку для основ взаимодействия с PowerSchool, написанную на PHP, и на прошлой неделе я пытался написать ее в цели c. Кажется, проблема в том, как я создаю HMAC (MD5) с паролем пользователя. Либо я использую шестнадцатеричный дайджест, чем дайджест, не уверен. Ошибка, которую я получаю с сервера - нечетное количество символов. Вот ссылка на класс библиотеки PHP, который я пытаюсь воссоздать: https://github.com/horvste/powerapi-php/blob/master/src/PowerAPI/Core.php Вот мой код в моем тестовом проекте, Основной класс командной строки: https://gist.github.com/anonymous/c40cdd99a826c06073aa Файл реализации категории NSString:

#import "NSString+MyAdditions.h"
@implementation NSString (MyAdditions)

- (NSString *) hmacMD5WithData: (NSString *) data
{
    const char *cKey  = [self cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
    const unsigned int blockSize = 64;
    char ipad[blockSize], opad[blockSize], keypad[blockSize];
    unsigned int keyLen = strlen(cKey);
    CC_MD5_CTX ctxt;
    if(keyLen > blockSize)
    {
        //CC_MD5(cKey, keyLen, keypad);
        CC_MD5_Init(&ctxt);
        CC_MD5_Update(&ctxt, cKey, keyLen);
        CC_MD5_Final((unsigned char *)keypad, &ctxt);
        keyLen = CC_MD5_DIGEST_LENGTH;
    }
    else
    {
        memcpy(keypad, cKey, keyLen);
    }
    memset(ipad, 0x36, blockSize);
    memset(opad, 0x5c, blockSize);

    int i;
    for(i = 0; i < keyLen; i++)
    {
        ipad[i] ^= keypad[i];
        opad[i] ^= keypad[i];
    }

    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, ipad, blockSize);
    CC_MD5_Update(&ctxt, cData, strlen(cData));
    unsigned char md5[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(md5, &ctxt);

    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, opad, blockSize);
    CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH);
    CC_MD5_Final(md5, &ctxt);

    const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2;
    char hex[hex_len];
    for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
    {
        snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]);
    }
    NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)];
    NSString *hash = [HMAC base64EncodedStringWithOptions:0];
    return hash;
}
@end

Спасибо, что нашли время взглянуть на этот вопрос!

1 ответ

Решение

Во-первых, не создавайте здесь свою собственную процедуру HMAC. Используйте CCHmac. Он встроен и обрабатывает HMAC+MD5 правильно.

Если это вообще возможно, я рекомендую перейти к документации API, а не пытаться перепроектировать другую кодовую базу. В PHP происходит много мелочей, которые вы можете пропустить; Документ API должен объяснить все это.

Если код PHP является единственной ссылкой, которая у вас есть, то вам следует разбить каждый фрагмент и посмотреть, где он идет не так. Например, убедитесь, что вы получаете данные авторизации в той же форме. Затем подтвердите, что для каждой программы с одинаковыми данными аутентификации создается один и тот же HMAC. Затем подтвердите, что при одинаковом HMAC каждая программа генерирует одинаковый ответ. И т.д. Где-то вы делаете что-то по-другому. Убедитесь, что вы используете Base64 по сравнению с необработанными данными в тех же местах (разработчики PHP имеют тенденцию обрабатывать строки Base64 так, как будто они на самом деле являются необработанными данными, что вызывает путаницу при переходе к ObjC).

И, конечно, вы должны проверить журналы сервера, чтобы убедиться, что ваш окончательный запрос соответствует запросам PHP.

Другие вопросы по тегам