mirror of
https://gitverse.ru/kpa39l/xmpp-server-prosody.git
synced 2026-09-29 09:45:02 +00:00
71 lines
4.9 KiB
Markdown
71 lines
4.9 KiB
Markdown
# OMEMO (XEP-0384) — проверка и публикация ключей (проверено 2026-08-28, nixg.ru)
|
||
|
||
## Главное: серверный модуль НЕ нужен
|
||
OMEMO полностью работает на клиентах. Prosody хранит ключи/девайс-листы через
|
||
PEP (`pep` в modules_enabled — уже включён). Если PEP включён — OMEMO работает
|
||
для любого клиента (Gajim, Conversations, Dino, Converse). Серверного
|
||
`mod_omemo` в prosody-modules НЕТ и он не нужен (это норма, не потеря).
|
||
|
||
## Converse v14 (веб-чат)
|
||
- OMEMO встроен: в dist лежат `libomemo.esm.min.js` + `curve25519_compiled.wasm`
|
||
(проверить: `grep -c omemo converse.min.js` > 0, есть `eu.siacs.conversations.axolotl`).
|
||
- ЕДИНСТВЕННАЯ опция в initialize(): `omemo_default: true` (default false) —
|
||
«шифровать по умолчанию, когда контакт поддерживает». Опции `allow_omemo`
|
||
в v14 нет (всегда доступен).
|
||
- При логине с omemo_default:true Converse сам генерит device id и публикует
|
||
devicelist + bundle в PEP. Проверять НЕ через UI — смотреть на диск.
|
||
|
||
## Авторитетная проверка — файлы PEP на диске (host bigbox)
|
||
Каталог данных: `data/` из docker-compose (в контейнере `/var/lib/prosody`),
|
||
имена узлов URL-encoded:
|
||
- devicelist: `data/<domain-encoded>/pep_eu%2esiacs%2econversations%2eaxolotl%2edevicelist/admin.list`
|
||
→ grep `["id"] = "N"` — все устройства пользователя (например 4040, 14035).
|
||
- bundle: `data/<domain>/pep_eu%2esiacs%2econversations%2eaxolotl%2ebundles%3a<deviceid>/admin.list`
|
||
→ должен содержать `identityKey`, 100× `preKeyPublic` (preKeyId 0..99),
|
||
`signedPreKeyPublic` + `signedPreKeySignature`, имя `bundle`.
|
||
- <domain-encoded>: nixg.ru → `nixg%2eru` (старый chin: `chat%2enixg%2eru`).
|
||
|
||
## slixmpp 1.17: publish в PEP-узел (рабочий рецепт)
|
||
Подключение по WebSocket, паттерн 1.17 (нет `.process()`, `connect` возвращает Future):
|
||
```python
|
||
import asyncio, ssl, slixmpp
|
||
from slixmpp.xmlstream import ET
|
||
ctx = ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
|
||
bot = slixmpp.ClientXMPP('user@domain', 'pass')
|
||
bot.ssl_context = ctx
|
||
bot.register_plugin('xep_0060')
|
||
bot.add_event_handler('session_start', ...) # в handler: send_presence(); await get_roster()
|
||
fut = bot.connect(('wss://xmpp.example.com/xmpp-websocket',))
|
||
await asyncio.wait_for(fut, 20); await asyncio.sleep(6) # дать событиям отработать
|
||
```
|
||
Publish (payload — СЫРОЙ lxml-элемент, не высокоуровневый API!):
|
||
```python
|
||
lst = ET.Element('{eu.siacs.conversations.axolotl}list')
|
||
ET.SubElement(lst, '{eu.siacs.conversations.axolotl}device', {'id': '7777'})
|
||
await bot['xep_0060'].publish(jid=JID, node='eu.siacs.conversations.axolotl.devicelist',
|
||
id='current', payload=lst)
|
||
```
|
||
Засады:
|
||
- `iq['pubsub']['publish']['item']...` + `ElementBase.append('list', {'xmlns':...})`
|
||
падает: `TypeError: ElementBase.append() takes 2 positional arguments but 3 were given`.
|
||
- `get_items` может вернуть 0 items даже когда узел НЕ пуст (семантика доступа PEP) —
|
||
диск `admin.list` авторитетнее. Проверять publish через чтение файла.
|
||
|
||
## Проверка веб-клиента headless (camofox)
|
||
- `camofox-browser open https://chat...` затем `eval` с `JSON.stringify(...)` —
|
||
иначе возвращается только `resultType`, без значения.
|
||
- Форма входа: `input[name=jid]`, `input[name=password]`, чекбокс `trusted`;
|
||
submit-кнопка `button.btn-primary` (текст «Войти»). Заполнять через
|
||
`el.value=...; el.dispatchEvent(new Event('input',{bubbles:true}))`, потом click.
|
||
- После входа в DOM: `document.body.innerText` содержит «Я на связи».
|
||
В DOM появляется строка «OMEMO» (кнопка в чате).
|
||
- Новый device от сессии виден в devicelist admin.list + каталог bundles:<id>.
|
||
|
||
## Очистка/удаление своего устройства из devicelist
|
||
Republish devicelist с оставшимися id (паттерн выше), id='current' — примет,
|
||
тестовый id исчезает из admin.list.
|
||
|
||
## Сопутствующее
|
||
- `omemo_default` в доке Converse: https://conversejs.org/docs/configuration/
|
||
(redirect с /docs/html/...). Единственная omemo-опция.
|
||
- Converse api.omemo недоступен из window.converse — проверять по диску, не по JS API. |