Как взломать картину и (не) получить BTC
Вызов принят
Для примера возьмём наиболее наглядную картину Bitcoin Initially Valued at $60.
В ней зашифрован приватный ключ к адресу 1HvEJG5JR84MVpncXcDVBqx65uY5odr6fP на котором находилось ~0.14 биткоина (~$1200).
На blockchain.info мы видим текстовую подсказку «Radix 6», запоминаем её и идём дальше.
Зорким взглядом исследуем и замечаем следующие моменты:
- Квадраты бывают только 6 цветов, а значит перед нами 6-символьная кодировка (radix 6)
- Ровные вертикальные линии через каждых 3 квадрата, делящие их на блоки, начиная с первого
- Паттерн идёт слева направо, состоит из 30 блоков и затем повторяется
6 символов явно недостаточно, чтобы закодировать в 270 символах классический WIF или HEX приватный ключ, однако для приватного ключа существует формат мини, он состоит как раз из 30 символов и работает по принципу brainwallet’а — sha256(«mini_private_key»).
Особенностью данного формата является обязательное начало с буквы S, пример — S6c56bnXQiBjk9mqSYE7ykVQ7NzrRy.
В последний раз посмотрим на картину и выпишем все цвета квадратов в первых 30 блоках, за исключением синих вертикальных разделителей, для удобства обозначив цвета одной буквой: Y = Yellow, G = Gray, R = Red, B = Blue, L = Light Blue, D = Dark Green
Получится:
'YGR', 'LBY', 'LBL', 'YBR', 'LGY', 'YYY', 'LBY', 'YBL', 'YDY', 'LGY', 'GRG', 'GRR', 'GDR', 'LBD', 'LBY', 'YDL', 'LBG', 'YYB', 'LYY', 'GRL', 'YYD', 'YGR', 'YDR', 'LBD', 'GYD', 'YRR', 'GRY', 'GYD', 'GRR', 'LGG'
Мы знаем, что первой буквой идёт S, а кодирование у нас 6-числовое, поэтому необходимо найти какой цвет за какую цифру отвечает.
Для числовых преобразований установим пакет baseconvert
pip install baseconvert
Сконвертируем букву S в шестнадцатеричную кодировку
echo -n "S" | od -A n -t x1 53
Полученный результат с помощью другой утилиты преобразуем в 6-числовую кодировку
python3 -m baseconvert --string true --number 53 --input-base 16 --output-base 6 215
Из этого делаем вывод, что
Y = 2 G = 1 R = 5
Половина задачи решена. Поскольку времени у нас не так мало, остальные 3 значения найдём ручным перебором, благо вариантов у нас немного и сразу напишем небольшой скрипт, который будет выдавать приватный мини-ключ.
#!/usr/bin/python3 import baseconvert values = ['YGR', 'LBY', 'LBL', 'YBR', 'LGY', 'YYY', 'LBY', 'YBL', 'YDY', 'LGY', 'GRG', 'GRR', 'GDR', 'LBD', 'LBY', 'YDL', 'LBG', 'YYB', 'LYY', 'GRL', 'YYD', 'YGR', 'YDR', 'LBD', 'GYD', 'YRR', 'GRY', 'GYD', 'GRR', 'LGG'] replace = {'Y':'2', 'G':'1', 'R':'5', 'B':'0', 'L':'3', 'D':'4'} #подставляем значения здесь key = [] base = 6 for char in values: for i, j in replace.items(): char = char.replace(i, j) v = baseconvert.base(char, base, 16, string=True) v = bytearray.fromhex(v).decode('ascii') key.append(v) print(''.join(key))
Запускаем…
python3 solve.py SnoMtVnKbtCGApncmTzEXSep4kD4Gs
По спецификации мини приватного ключа, мы можем проверить его валидность, добавив знак вопроса в конец и захешировав sha256. Если первые два символа являются нулями, то ключ считается валидным.
echo -n SnoMtVnKbtCGApncmTzEXSep4kD4Gs? | sha256sum 00edc14de4c175a2a8ccb213e4d5deee738782a8213c25328a7b035d3c728866
Нам повезло, приватный ключ валиден.
Теперь идём на www.bitaddress.org (так быстрее) и вставляем получившийся приватный ключ во вкладку Wallet Details.
Забираем приватный ключ в формате WIF (5KfNkSeQwNgjHr7cRErzDmq5XdUm8qc94YM3iEN5YaMYoA2UGky) и импортируем его в биткоин-клиент.
Так, что тут у нас?..
Упс…

