Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Авторизация в Jabber'e 
V
    Опции темы
scroollocker
Дата 17.7.2011, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Пол дня мучаюсь, все идет нормально, но остановился на авторизации MD5-Digest составления response. Нашел такой алгоритм:
Цитата

Алгоритм вычисления строки ответа response имеет следующую формулу:
response-value  =
         HEX( KD ( HEX(H(A1)),
                 { nonce-value, ":" nc-value, ":",
                   cnonce-value, ":", qop-value, ":", HEX(H(A2)) }))
      A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
           ":", nonce-value, ":", cnonce-value }
      A2 = { "AUTHENTICATE:", digest-uri-value }

Где: 

Выражение { a, b, ... } — означает сложение строк a, b

HEX(n) — 16-байтовый MD5-хеш n, приведенный в 32 байтовую Hex-строку в нижнем регистре. Фактически строковое представление дайджеста MD5.

H(s) — 16-байтовый MD5-хеш строки s

KD(k, s) — объединение данных (строк) k, s

H({k, ":", s}) — 16-байтовый MD5-хеш, полученный в результате сложения строки k, ":", S


вот так делаю: 

Код

AnsiString GetResponse(u_char*uname,u_char*pass,u_char*realm,AnsiString nonce,AnsiString cnonce){
        AnsiString nc   = "00000001";
        AnsiString qop  = "auth";
        u_char buf[256];
        AnsiString A1,A2,HA1,HA2,result;
        u_char d_uri[100];
        memset(buf,0,256);
        memset(d_uri,0,100);
        strcat(d_uri,"xmpp/");
        strcat(d_uri,realm);

        MD5 *md5 = new MD5();

    // ВЫЧИСЛЯЕМ А1 по формуле RFC 2831

    //  A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
    //           ":", nonce-value, ":", cnonce-value, ":", authzid-value }

        sprintf(buf,"%s:%s:%s",uname,realm,pass);
        md5->feed(buf,strlen(buf));
        md5->finalize();
        A1 = md5->binary().c_str();
        md5->reset();

        A1 += ":"+nonce+":"+cnonce;

    // ВЫЧИСЛЯЕМ А2 по формуле RFC 2831

    //  A2       = { "AUTHENTICATE:", digest-uri-value }

        A2.sprintf("AUTHENTICATE:%s", d_uri);

    //HEX(H(A1))

        md5->feed(A1.c_str());
        md5->finalize();
        HA1 = md5->binary().c_str();
        md5->reset();
        md5->feed(HA1.c_str());
        md5->finalize();
        HA1 = md5->hex().c_str();
        md5->reset();

    //HEX(H(A2))

        md5->feed(A2.c_str());
        md5->finalize();
        HA2 = md5->binary().c_str();
        md5->reset();
        md5->feed(HA2.c_str());
        md5->finalize();
        HA2 = md5->hex().c_str();
    md5->reset();

    // ВЫЧИСЛЯЕМ RESPONSE по формуле RFC 2831
    //  HEX( KD ( HEX(H(A1)),
    //     { nonce-value, ":" nc-value, ":",

    //      cnonce-value, ":", qop-value, ":", HEX(H(A2)) }))    
    
        result = HA1+nonce+":"+nc+":"+cnonce+":"+qop+":"+HA2;        
        md5->feed(result.c_str());
        md5->finalize();
        result = md5->hex().c_str();

    delete md5;
        return result;
}


После отправки сервер возвращает не дружественное: 
Цитата

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure/>


Использую компонент md5 шифрования, взятый из компонента gloox.(прикреплен к теме)

Подскажите ошибки в коде, или направте на рабочий пример авторизации  MD5-Digest C++

С уважением, Андрей


Это сообщение отредактировал(а) scroollocker - 17.7.2011, 13:55

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  md5.rar 5,57 Kb
PM MAIL WWW ICQ Jabber   Вверх
artsb
Дата 17.7.2011, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Я как-то решал похожую задачу. Только делал авторизацию для SMTP.
По последовательности действий, вроде бы, всё правильно.
Единственное, не знаю насколько верны значения: nc, qop и d_uri.

Теперь по коду:
Код

A1 = md5->binary().c_str();

Так делать нельзя. Метод binary().c_str() возвращает указатель (char*) на строку (массив символов). Вы приравниваете его строке (AnsiString). Но всё дело в том, что если в этом массиве встретится нулевой символ ('\0' - символ конца строки), то в результирующей строке у вас будут указаны не все данные. Так же, может произойти и обратное: в этом массиве может не оказаться нулевого символа и причём, его может не оказаться в конце массива. А это значит, что в результирующую строку может попасть мусор.
Поэтому, нужно делать как-то так:
Код

A1.SetLength(16);
memcpy(&A1[0], &(md5->binary())[0], 16);

То же самое и в остальных местах.

Но лучше всего, отказаться от AnsiString и использовать std::string. Тогда memcpy не понадобится.

Это сообщение отредактировал(а) artsb - 17.7.2011, 23:28


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
xvr
Дата 18.7.2011, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(artsb @  17.7.2011,  23:25 Найти цитируемый пост)
Теперь по коду:
Код

A1 = md5->binary().c_str();

Так делать нельзя. 
Я бы сказал - дважды нельзя. По исходному алгоритму требуется не бинарное представление MD5, а hex.


PM MAIL   Вверх
scroollocker
Дата 18.7.2011, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



xvr, 
Цитата

H( { username-value, ":", realm-value, ":", passwd } )

Цитата

H(s) — 16-байтовый MD5-хеш строки s
HEX(n) — 16-байтовый MD5-хеш n, приведенный в 32 байтовую Hex-строку в нижнем регистре. Фактически строковое представление дайджеста MD5.

в прикрепленном md5, как я понял, функция binary() как раз и возвращает этот 16 байтовый хэш. А вот где достать именно этот hex. если использовать и там hex и там hex получится не так. или почему написано H и HEX?


artsb, 
Да действительно у меня строка отрезалась на \0 символе. Сделал как вы сказали, строка вроде начала получаться целой. но сервер все равно не хочет меня авторизовать. 

Может быть есть какой нибудь пример?, а то для делфи море, для Си++ ни одного.

Это сообщение отредактировал(а) scroollocker - 18.7.2011, 21:35
PM MAIL WWW ICQ Jabber   Вверх
xvr
Дата 18.7.2011, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(scroollocker @  18.7.2011,  21:16 Найти цитируемый пост)
в прикрепленном md5, как я понял, функция binary() как раз и возвращает этот 16 байтовый хэш. 

Да, действительно. Но тогда операции с А1 следует проводить с осторожностью - там не текст, а бинарные данные. В частности md5->feed(A1.c_str()); делать нельзя - обрежет по 0

Добавлено через 59 секунд
md5->feed(HA1.c_str()); - тут тоже ошибка

PM MAIL   Вверх
scroollocker
Дата 18.7.2011, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Значит все таки нужно отказаться от AnsiString. А зависит ли то, что я кодирую обычную строку, не UTF8? увидел в исходниках миранды, что там еще перед этим в UTF8 кодиться
PM MAIL WWW ICQ Jabber   Вверх
artsb
Дата 18.7.2011, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Как сказал xvr, нужно поизбавляться от указанных им ошибок. А потом уже будем смотреть дальше. Поэтому, как я уже говорил, лучше избавьтесь от AnsiString.

Добавлено через 42 секунды
Цитата(scroollocker @  18.7.2011,  21:39 Найти цитируемый пост)
увидел в исходниках миранды, что там еще перед этим в UTF8 кодиться 

По идее, об этом должно было упоминаться в спецификации...

Добавлено через 1 минуту и 9 секунд
Так что, попробуйте конвертнуть.

Добавлено через 2 минуты и 56 секунд
Я когда делал авторизацию по SMTP, открыл спецификацию, нашёл описание этих "манипуляций" со строками. Там же был указан результат для конкретных данных из примера. Ну я и возился с этими же самыми данными, пока не получил нужный результат из примера smile


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
scroollocker
Дата 18.7.2011, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



Посмотрел RFC2831 http://www.ietf.org/rfc/rfc2831.txt. Оказалось нужно еще и в UTF8 кодировать. 

Ну теперь надо исправлять ошибки. 

xvr, artsb

Спасибо. =)

artsb
Цитата

Ну я и возился с этими же самыми данными, пока не получил нужный результат из примера

Наверное, я тоже так буду делать, нашел Онлайн шифрователь пакетов. Буду мучить =)

Это сообщение отредактировал(а) scroollocker - 18.7.2011, 22:02
PM MAIL WWW ICQ Jabber   Вверх
artsb
Дата 18.7.2011, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Цитата(scroollocker @  18.7.2011,  21:50 Найти цитируемый пост)
Оказалось нужно еще и в UTF8 кодировать. 

Кстати, необязательно:
Цитата

   The "username-value", "realm-value" and "passwd" are encoded
   according to the value of the "charset" directive. If "charset=UTF-8"
   is present, and all the characters of either "username-value" or
   "passwd" are in the ISO 8859-1 character set, then it must be
   converted to ISO 8859-1 before being hashed. This is so that
   authentication databases that store the hashed username, realm and
   password (which is common) can be shared compatibly with HTTP, which
   specifies ISO 8859-1. A sample implementation of this conversion is
   in section 8.

Всё зависит от параметра "charset".


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
scroollocker
Дата 18.7.2011, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



А что надо написать в charset чтобы не использовать UTF8?
PM MAIL WWW ICQ Jabber   Вверх
artsb
Дата 18.7.2011, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Цитата(scroollocker @  18.7.2011,  22:11 Найти цитируемый пост)
А что надо написать в charset чтобы не использовать UTF8? 

Эм... Не знаю smile Нужно читать всё остальное. А utf-8 похоже используется как кодировка по умолчанию.


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
scroollocker
Дата 18.7.2011, 23:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



artsb, 
Подправил сейчас, как вы написали, и функция возвращает нормальный md5. Я прям счастлив =) спасибо вам

Вот только все равно не авторизовывается. Похоже всё дело в UTF8. И возник сразу вопрос. А как средствами Builder'a перевести char * или string в UTF8? =)

PM MAIL WWW ICQ Jabber   Вверх
artsb
Дата 18.7.2011, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Цитата(scroollocker @  18.7.2011,  23:00 Найти цитируемый пост)
Похоже всё дело в UTF8. И возник сразу вопрос. А как средствами Builder'a перевести char * или string в UTF8? =)

Сначала, переводите char в utf-16 с помощью MultiByteToWideChar.
Далее с помощью WideCharToMultiByte переводите из utf-16 в utf-8.


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
artsb
Дата 19.7.2011, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Код

wchar_t *CharToUTF16(char *sString) {
    wchar_t *Result;
    unsigned int uiLen;

    if(!sString) {
        return NULL;
    }

    uiLen = MultiByteToWideChar(1250, 0, sString, -1, NULL, 0);
    if(uiLen < 1) {
        return NULL;
    }

    try {
        Result = new wchar_t[uiLen];
    }
    catch(...) {
        Result = NULL;
    }

    if(!Result) {
        return NULL;
    }

    uiLen = MultiByteToWideChar(1250, 0, sString, -1, Result, uiLen);
    if(uiLen < 1) {
        delete [] Result;
        Result = NULL;
    }

    return Result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
unsigned char *UTF16ToUTF8(wchar_t *sString, unsigned int &uiResultLen) {
    unsigned char *Result;
    unsigned int uiLen;

    uiResultLen = 0;

    if(!sString) {
        return NULL;
    }

    uiLen = WideCharToMultiByte(CP_UTF8, 0, sString, -1, NULL, 0, NULL, NULL);
    if(uiLen < 1) {
        return NULL;
    }

    try {
        Result = new unsigned char[uiLen];
    }
    catch(...) {
        Result = NULL;
    }

    if(!Result) {
        return NULL;
    }

    uiLen = WideCharToMultiByte(CP_UTF8, 0, sString, -1, Result, uiLen, NULL, NULL);
    if(uiLen < 1) {
        delete [] Result;
        Result = NULL;
    }
    else {
        uiResultLen = uiLen;
    }

    return Result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
    char CStr[] = "тест string";
    wchar_t *WString;
    char *CString;
    unsigned int UTF8Len;

    WString = CharToUTF16(CStr);
    if(!WString)
        return 1;

    CString = UTF16ToUTF8(WString, UTF8Len);

    delete [] WString;

    if(!CString)
        return 1;

    delete [] CString;

    return 0;
}



--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
scroollocker
Дата 19.7.2011, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.{--}.



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.9.2010

Репутация: нет
Всего: нет



artsb, 
все работает авторизовывает меня   smile  smile 

Спасибо вам огромное)
PM MAIL WWW ICQ Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0588 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.