2023-01-12

Tor v3

Как обычно, несколько месяцев назад разобрался как получать ключи torv3 (и хранить их компактно) и уже всё забыл потому что не записал. Сама задача вроде простая. В системе tor v3 поменялся алгоритм формирования адресов .onion - и теперь там не sha1+rsa а es25519. Системы генерации "красивых" адресов вроде mkp224o выдают длиннющие последовательности из получившегося имени, приватного ключа, публичного ключа. А уж если это надо ещё и хранить... Фактически достаточно хранить всего 32 байтика на ключ (seed) - а уже из этого получать и приватный ключ, и публичный, и domain name. Кстати очень похожий подход в yggdrasil, только там "ванильные" ключи суть те, у кого начальная часть много нулей в начале, или какая-то красивая последовательность внутри из шестнадцатеричных чисел. Ну а ещё лучше те и другие критерии вместе. Как обычно люблю делать всё это на perl - а в итоге пришлось влезать в .xs - так как в Crypto::Ed25519 не хватило функций для работы с ключаим (потребовалась возможность влезать внутрь некоторых бывших атомарных операций над ключом). Итак, суть алгоритма ed25519. Генерируется некая случайная последовательность 256 бит (или 32 байта). Это наш seed. Фактически это уже можно считать нашим "секретным ключом", и некоторые разработчики его так и воспринимают. seed преобразуется в keypair. Вся магия вот в этой функции (выдрана из Crypt-Ed25519-1.05-0/ed25519/src/keypair.c).
void ed25519_create_keypair(unsigned char *public_key,
           unsigned char *private_key, const unsigned char *seed) {
    ge_p3 A;

    sha512(seed, 32, private_key);
    private_key[0] &= 248;
    private_key[31] &= 63;
    private_key[31] |= 64;

    ge_scalarmult_base(&A, private_key);
    ge_p3_tobytes(public_key, &A);
}
То есть считается private_key = sha512(seed), фиксируются несколько бит и проводятся операции над curve25519 и в итоге получаем public_key. Вот после sha512 и битовыми операциями - получаем так называемый expanded_key. И private key от tor v3 собственно и есть этот expanded_key. А. Теперь вспомнил почему забросил эту тему :) Вместо того, чтобы показать seed размером 32 байта - mkp224o показывает нам кучу всего ненужного: expanded_key размером 64 байта, public_key в 32 байта, который получается из expanded, и onion адрес, который производный от public_key (+ байт версии и 2 байта хешсуммы в конце). Так что хранить придётся 64 байта на ключ или перезапускать mkp224... Печаль.