Blinded ID в Session и что с ними не так
Blinded ID (aka "слепые" айди и т.п) - алгоритм деривации ID пользователя, который является публичным ключом Curve25519, для открытых групп в Session, для того чтобы скрыть настоящий ID пользователя.
Всего существует две версии данного алгоритма:
На данный момент полностью реализованной является legacy версия, а поддержка новой версии есть только в libsession и вроде как планируется в pysogs.
Важно: Все математические операции выполняются в поле Fp кривой ed25519, манипуляции со скалярами (редуцирование, инвертирование) выполняются в поле Fn (order field)
Один ключ -> два ключа. Legacy версия.
Алгоритм
Для работы алгоритма нам понадобится:
- Генерируем т.н "blinding factor": хэшируем с помощью Blake2B публичный ключ сервера и редуцируем результат.
Обозначим, какk
. - Из ID пользователя убираем префикс 05 и переводим его в ed25519.
Обозначим, какA
. - Умножаем
k
наA
и получаем ключ ed25519, который является одним из возможных "слепых" id.
Обозначим, какkA
.
Сломанное условие
Как следует из заголовка, legacy версия генерирует 2 возможных "слепых" ID.
Второй возможный ID (kA2
) генерируется на основе kA
, только с изменённым (XOR на 128) sign битом.
И для того чтобы выяснить какой из двух ключей следует использовать, pysogs предлагает следующий код:
if kA[31] & 0x80: return kA[0:31] + bytes([kA[31] & 0x80])
Однако это условие совершенно не работает, поэтому в реализации клиентов пошли другим путём - получение "слепого" id из приватного ключа, вместо того чтобы получать его из публичного ключа. Таким образом сервер не знает наверняка, какой ключ из двух следует использовать, и надеется на клиент в результате чего в теории может произойти раздвоение пользователя.
Обратимая необратимость
Так же немало важным является то, что legacy версия (а фактически единственная версия на момент написания статьи) является обратимой вопреки всем заявлениям.
Для этого достаточно инвертировать полученный ранее "blinding factor", умножить его на слепой id, полученный ключ перевести в Curve25519 и в результате мы имеем ID пользователя.
Один ключ -> один ключ. Новая версия
На момент написания статьи эта версия реализована только в libsession, и поэтому может поменяться.
Самое главное отличие этой версии от legacy в том, что в процессе генерации "blinding factor" принимает участие ID пользователя вместе с публичным ключом сервера, что, в свою очередь, исключает возможность обратимости, как это было с legacy версией.
- Генерируем "blinding factor": хэшируем с помощью Blake2B ID пользователя (вместе с префиксом) и публичный ключ сервера и редуцируем результат.
Обозначим, какk
. - Переводим ID пользователя из Curve25519 в ed25519.
Обозначим, какA
. - Умножаем скаляр
k
наA
На выходе получаем единственный Blinded ID для конкретного пользователя на конкретном сервере.