| | |
| Shaos wrote: Интересный способ идентификации сообщений выбран в ii (перекочевавший затем в IDEC и использующийся в двух самых старых серверах реализующих этот протокол - ii-php написанном на PHP и iing написанном на Python) - сервер формирует текст сообщения для сохранения добавляя к нему заголовки, а именно: - tags - теги (используются только для `repto` и для идентификатора `ii/ok`)
- echoarea - основная эхоконференция, в которую помещается сообщение
- date - число секунд от эпохи unix, в utc
- msgfrom - отправитель
- addr - адрес отправителя (практического смысла не имеет, служит для того, чтобы узнавать, с какой станции пришло сообщение)
- msgto - пользователь, которому предназначено сообщение (либо All)
- subj - тема сообщения
- пустая строка
- и далее - текст сообщения
Пример из документации: (в данном случае наличие ключевого слова repto в тегах означает, что это сообщение является ответом на сообщение с указанным ID - здесь IZXhLBKJx0rhx0lXYu3L) Далее по всему этому считается хэш SHA256 (32 байта), бинарное представление которого переводится в base64 (что даёт 43 символа), от которого берутся первые 20 символов (46.9% от всей строки), но т.к. base64 наряду с буквами A...Z a...z и цифрами 0...9 ещё имеет 2 дополнительных небуквоциферных символа + и / для пущей читабельности они заменяются на символы A и z (именно так - большая A и маленькая z) - уникальность хэша от этого немного портится (покрытие уменьшается в 1.88 раз с 64^20 до 62^20, что даёт 7e35 вариаций), но хэш становится "безопасным" для передачи как угодно. При передаче сообщения между сервером и клиентом также используется base64 (но только всего сообщения) - в виде base64url, в котором + заменяется на - а / заменяется на _ | |
| | |
Для отправки сообщения от клиента к узлу ii/IDEC с самого начала применяется следующий формат:
Пример:
Это сообщение заворачивается в base64url и засылается на узел либо через метод GET:
URL/u/point/PAUTH/B64STRINGлибо через метод POST:
URL/u/point
pauth=PAUTH&tmsg=B64STRINGгде PAUTH - строка авторизации для данного пользователя (поинта) - по сути пароль (который должен быть свой для каждого поинта).
Как можно видеть тут прямым текстом в сеть передаётся пароль - даже в случае https:// если он идёт через GET, то он считай засвечен (а в случае http:// будет засвечен и через POST), поэтому я думаю можно сделать альтернативный способ аутентификации пользователя скажем через подпись HMAC-RIPEMD-160-96. Алгоритм HMAC это hash-based message authentication code (код аутентификации сообщения на основе хеша), который использует один секретный ключ, известный обеим сторонам, и над каким-то стандартным хешом - в данном случае это RIPEMD-160 (алгоритм хеширования с наименьшей длиной хеша, который ещё не сломали), причём этот алгоритм был представлен ещё в 1992 году (т.е. ему уже 32 года!) - он в частности используется в биткоине (вместе с SHA-256). Ну и для укорачивания такой подписи берутся первые 96 бит (12 байт). Это всё стандартизовано на уровне RFC:
RFC2104 (February 1997) - HMAC: Keyed-Hashing for Message Authenticationhttps://datatracker.ietf.org/doc/html/rfc2104RFC2286 (February 1998) - Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128https://datatracker.ietf.org/doc/html/rfc2286RFC2857 (June 2000) - The Use of HMAC-RIPEMD-160-96 within ESP and AHhttps://datatracker.ietf.org/doc/html/rfc2857Конечно было бы лучше использовать SHA-256, но RIPEMD-160 проще в вычислительном плане, а нам надо будет его считать на слабых платформах. Вобщем суть такая - секретный ключ (это может быть строка текста длиной до 20 символов) загружается на узел через секьюрное соединение (https:// или скажем через емейл сисопу) один раз. Далее когда пользователь хочет отправить сообщение на узел (в описанном выше формате) по несекьюрному каналу, то его клиент считает по телу сообщения и секретному ключу подпись HMAC-RIPEMD-160-96 и посылает 12-байтовый результат как PAUTH (можно наверное в base64url его завернуть), а сервер при получении будет считать по полученному телу сообщения свой вариант HMAC-RIPEMD-160-96 и будет сравнивать с присланной подписью - если результат совпадёт, то отправитель считается аутентифицирован (плюс будет проверена целостность самого сообщения). До кучи в урл можно добавить кодировку, на тот случай если софт поинта не поддерживает UTF8:
URL/u/point2/koi7/B64AUTH/B64STRINGдля больших сообщений можно задействовать метод POST:
URL/u/point2/koi7/B64AUTH
TEXT
причём тело сообщения в данном случае можно заслать прямым текстом без кодировки (Content-Type: plain/text)