habrahabr

Что под капотом у Jaxx. Энтропия из коробки 128 бит

  • четверг, 20 сентября 2018 г. в 00:19:41
https://habr.com/post/423707/
  • Хранение данных
  • Криптография
  • Криптовалюты
  • Децентрализованные сети
  • JavaScript


Немного скомкано, записал чтобы не забыть. Должны быть интересны комментарии хабракриптосообщества.

Решил проверить, насколько криптоустойчиа Brainwallet система резервного копирования мультивалютного кошелька Jaxx и что означают секретные слова на уровне кода.

Для начала сделал копию свежеустановленного Google extension кошелька себе в рабочую папку. Подправил файлы для получения возможности редактирования.

В Notepad++ есть замечательные функции для поиска в файлах и плагины для форматирования кода, так что поиски и добавление строчек вида console.warn(«bits=» + bits) помоголо быстро разобраться что происходит при генерации и восстановлении кошелька. Также обнаружен скрытый от пользователя функционал, вероятно позволяющий поднять уровень криптостойкости до параноидального.

Итак, при создании кошелька:

1. Генерируесся 128 псевдослучайных бит с помощью rng:

 function generateMnemonic(strength, rng, wordlist) {
  strength = strength || 128
  rng = rng || randomBytes
  var hex = rng(strength / 8).toString('hex')
  console.warn('hex=' + hex)
  return entropyToMnemonic(hex, wordlist)
}

2. Рассчитывается 4х битная контрольная сумма

3. Суммарный битовый массив разбивается на куски по 12 бит, и конвертируется в Integer. Получаем 12 индексов для кодовой таблицы.

4. Из кодовой таблицы размером 2225 слов собирается строка из слов для бэкапа кошелька.

5. На основании выбора создаются разные кошельки путём применения к 128 битному seed различных хеширующих алгоритмов.

var jaxx;
(function (jaxx) {
    var Seed = /** @class */ (function () {
        function Seed() {
        }
        Seed.generateMnemonic = function () {
            return thirdparty.bip39.generateMnemonic();
        };
        Seed.validateSeed = function (seed) {
            return (thirdparty.bip39.validateMnemonic(seed)) ? true : false;
        };

Внутренности thirdparty содержат реализации множества различных алгоритмов, можно перекраивать jaxx под свои нужды.

 hash160: hash160,
  hash256: hash256,
  ripemd160: ripemd160,
  sha1: sha1,
  sha256: sha256

И массу интересного кода, в котором я продолжаю копаться.

При восстановлении кошелька, найденные в кодовой таблице индексы дополняются не значащим 0 до 12 бит, проверяется контрольная сумма, из полученного seed сразу генерируются ключи и запускается синхронизация с блокчейном.

words=boil,matter,crawl,clean,choice,gasp,clay,defy,crew,amount,cushion,pretty
chunks=00011001000,10001001010,00110010101,00101010010,00101000001,01100000001,00101010001,00111001101,00110011010,00001000000,00110110011,10101010001
bits=000110010001000100101000110010101001010100100010100000101100000001001010100010011100110100110011010000010000000011011001110101010001
checksum=0001


Для меня весь этот опыт оказался любопытным материалом для углубления знакомства с крипто.

P.S. И да, к чему это я:

Как вы считаете, если нейрокриптоанализ применить к этому алгоритму, получится ли ускорить взлом кошелька, private key которого закодирован детерминистически из массива bits и использован как seed для екскольких кошельков.

Буду рад и признателен примерам кода на python, любопытно измерить скорость подбора ключа на разном железе.