В этой статье мы поговорим о извлечение значений подписи ECDSA R, S, Z из блокчейна Биткойн, но для начало вспомним о самой первой серьезной уязвимости в транзакции блокчейн которую обнаружил Нильс Шнайдер (Nils Schneider он жеtcatm)

Биткоин-разработчик и владелец "BitcoinWatch" & "BitcoinCharts".

4.1 История опасных случайных Атак на Биткоин
4.1 История опасных случайных Атак на Биткоин

Document [PDF]: Private Key Recovery Combination Attacks: On Extreme Fragility of Popular Bitcoin Key Management, Wallet and Cold Storage Solutions in Presence of Poor RNG Events

25 декабря 2012 года Нильс обнаружил потенциальную слабость в некоторых транзакциях блокчейна Биткойна.

Посмотрите на эту транзакцию:

transaction: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1



input script 1:
30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff

input script 2:
30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff

Эта транзакция имеет два входа и один выход.
Если вы внимательно посмотрите на два входных скрипта, то заметите, что в начале и в конце есть довольно много одинаковых байтов.
Эти байты в конце представляют собой закодированный в шестнадцатеричном формате публичный ключ адреса, на который расходуются монеты, так что в этом нет ничего плохого.
Однако первая половина скрипта — это фактическая подпись (r, s):

r1: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
r2: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1

s1: 44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2: 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab

Как видите, r1 равно r2. Это огромная проблема.

Мы сможем восстановить закрытый ключ на этот публичный ключ:

04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff

Для этого мы можем воспользоваться простой формулой из школьной алгебры ;)

private key = (z1*s2 - z2*s1)/(r*(s1-s2))

Нам просто нужно найти z1 и z2

Это хэши выходов, которые нужно подписать. Давайте получим выходные транзакции и посчитаем их (вычисляется OP_CHECKSIG):

z1: c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e
z2: 17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

Далее упакуем все эти значение в один Python-скрипт: vulnerabilityR.py

Python-скрипт: vulnerabilityR.py
Python-скрипт: vulnerabilityR.py

p — это всего лишь порядок G, параметра кривой secp256k1, используемой Биткойном.

Создадим поле для наших вычислений:

K = GF(p)
K((z1*s2 - z2*s1)/(r*(s1-s2)))

Запускаем скрипт: python3 vulnerabilityR.py

Далее наш скрипт: vulnerabilityR.py вычислит закрытый ключ в этом поле:

ADDR: 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm
WIF:  5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ
hex:  c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96
Проверяем закрытый ключ на сайте bitaddress
Проверяем закрытый ключ на сайте bitaddress

Закрытый ключ найден!

https://www.blockchain.com/btc/address/1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm


0.1638109 BTC
0.1638109 BTC

Конечно же, разработчики Биткоина устранили эту уязвимость внедрив детерминированные функции.

Эта функция RFC 6979 вносит в подпись Биткоина элемент случайности, что усиливает криптостойкость транзакции ECDSA

Document [PDF]: RFC 6979: Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)


Как мы знаем на практике в блокчейне Биткоина есть совершенно другие уязвимые транзакции.

Ранее мы опубликовали статью: «Одна слабая транзакция в ECDSA в блокчейне Биткоина и с помощью Lattice Attack мы получили Private Key к монетам BTC»

https://habr.com/ru/post/671932/
https://habr.com/ru/post/671932/

Теперь давайте самостоятельно получим публичный ключ Bitcoin ECDSA и значение R, S, Z из файла «RawTX.json» (который мы получили в 01BlockchainGoogleDrive )

  • Для этого воспользуемся Терминалом для Google Colab [TerminalGoogleColab]

  • Давайте перейдем по репозитории «CryptoDeepTools» для детального криптоанализа и разберем в детали работу Bash-скрипта: getsign.sh

Команды
Команды
Файлы
Файлы
Код нашего Bash-скрипта: getsign.sh
Код нашего Bash-скрипта: getsign.sh

И так давайте разберем в детали всю работу Bash-скрипта: getsign.sh

cat RawTX.json > index.json

Делаем копию файла RawTX.json в новый файл index.json

for run in {1..4}; do

Открываем ЦИКЛ так как в файле index.json 4 строк берем {1..4}

export LINE=1 ; sed -n "${LINE}p" index.json > index2.json

Утилита export берет строку №1 и сохраняет в новом файле index2.json

sed -i '1d' index.json

Утилита sed удаляет строку №1 из файла index.json

Утилита echo создает нам Python-скрипт fileopen.py
Утилита echo создает нам Python-скрипт fileopen.py
python3 fileopen.py

Запускаем Python-скрипт fileopen.py и с успешно создает новый Bash-скрипта: signscript.sh

chmod +x signscript.sh
./signscript.sh

Получаем права на Bash-скрипт: signscript.sh

В результате запускается Python-скрипт breakECDSA.py который в итоге извлекает из RawTX значение R, S, Z и публичный ключ Bitcoin

Все это сохраняется в файл: "signatures.json"

файл: "signatures.json"   публичный ключ Bitcoin и значение R, S, Z
файл: "signatures.json" публичный ключ Bitcoin и значение R, S, Z
rm signscript.sh
rm fileopen.py

Утилита rm удаляет Python-скрипт fileopen.py и успешно создает новый Bash-скрипта: signscript.sh

done

В итоге все завершится после 4-х циклов

rm index.json

Цикл закрывается и утилита rm удаляет index.json

Bash-скрипт: getsign.sh Завершает работу!

Теперь мы научились:

  • Получать публичный ключ Bitcoin из ECDSA

  • Получать значение R, S, Z из ECDSA

  • Применить это для криптоанализа

Исходный код: https://github.com/demining/CryptoDeepTools/blob/main/02BreakECDSAcryptography

Telegram: https://t.me/cryptodeeptech

Видеоматериал: https://youtu.be/BYd-cuFRZmM

Источник: https://cryptodeep.ru/break-ecdsa-cryptography


Комментарии (5)


  1. mayorovp
    03.07.2022 11:21
    +4

    Так в чём уязвимость-то?


    1. vassabi
      03.07.2022 14:10

      насколько я понял, уязвимость в том, что для таких параметров можно вычислить ключ, которым биткойны переводятся с этих адресов - в заметке вверху написано, что так уже увели 59 BTC (на момент 28 декабря 2013 года)


      1. mayorovp
        03.07.2022 14:59

        Для каких параметров?


        1. antonblockchain
          03.07.2022 15:21
          +2

          пары ключей приватный и публичный не одинаково сильные.
          есть слабые пары ключей.
          в статье метод проверки пар ключей на слабость.
          после этого проверяешь все публичные ключи в которых что-то есть в блокчейне на слабость.

          и информируешь владельца слабой пары ключей что ключи у него слабые.

          единственно вот этого делать не надо «Проверяем закрытый ключ на сайте bitaddress.»
          а надо сгенерировать из закрытого ключа открытый самостоятельно.

          потому что после проверки у сайта будет пара открытых и закрытых ключей.
          а это не очень хорошо.


          1. mayorovp
            03.07.2022 15:23

            "Запустить скрипт" — это точно метод проверки? Меня больше интересует что скрипт делает...