Reused R Bitcoin avatar
Reused R Bitcoin

Pricing

from $100.00 / 1,000 results

Go to Apify Store
Reused R Bitcoin

Reused R Bitcoin

Detection & research tools for repeated ECDSA & Schnorr nonces (r) in Bitcoin transactions

Pricing

from $100.00 / 1,000 results

Rating

0.0

(0)

Developer

Abdo Abdo

Abdo Abdo

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

0

Monthly active users

6 hours ago

Last modified

Share

reused-r-bitcoin

Detection & research tools for repeated ECDSA & Schnorr nonces (r) in Bitcoin transactions

⚠️ important :

these tools are for educational purposes. Any incorrect or harmful use is the responsibility of the user.

What is “r-repeat” :

r-repeat means the same ECDSA or Schnorr nonce (k) — and thus the same r value — was used more than once with the same private key in Bitcoin signatures. If that happens, the signatures leak enough information that someone could recover the private key. This turns otherwise secure signatures into a critical vulnerability.

How does r repeat? :

  1. Weak or insufficient randomness (CSPRNG): the system or device didn’t provide enough entropy when signing.

  2. Programming bug: the random generator is re-seeded incorrectly or the same nonce buffer is reused.

  3. Incorrect deterministic nonce implementation: RFC6979 is safe when implemented correctly; buggy implementations break safety.

  4. Re-using the same private key across apps / chains: one weak environment can compromise all signatures made with that key.

  5. Weak key-generation (brainwallets): low-entropy passphrases or predictable key derivation lead to weak keys and weak nonces.

  6. Hardware / firmware faults: buggy devices can unintentionally reuse nonces (e.g., after power loss).

    Why is this dangerous :

Because the nonce k is the core secret that makes each signature unique. If the same k is used twice with the same private key, the signatures alone (no access to the private key required) may allow an attacker to compute the private key. In short: nonce reuse breaks the security goal of signatures.

What you should do (safety tips) :

  1. Use well-audited libraries (e.g., secp256k1/OpenSSL) and keep them updated.
  2. Prefer RFC6979 deterministic signing only via proven implementations.
  3. Use hardware wallets or HSMs with good security reviews for high-value keys.
  4. Never reuse a private key across unrelated apps/chains.
  5. Avoid brainwallets or passwords-as-keys; use proper key generation.
  6. Monitor signatures: detect repeated r values and act immediately if found.

Requirements :

Python 3.10 or newer

Sufficient free storage space to download transaction data (depends on analysis size)

Internet connection when fetching blockchain data or using APIs

Security Notice :

These tools are designed purely for analysis and research — they do not collect any user data, results, or personal information in any form.

Running the tools with an internet connection is safe, as long as you trust the source.

You can always review the source code yourself to verify what each tool does and ensure it meets your security standards.

Installation :

1• Clone repo

git clone https://github.com/abdallahbn31/reused-r-bitcoin
cd reused-r-bitcoin

2• Install requirements

$pip install -r requirements.txt

How to operate tools + example :

$addresses.txt

This is list of addresses that included r-duplication vulnerability

If you want to check balances of these addresses, use this script.

$check_adds.py

usage :

$python check_adds.py --input addresses.txt --output balances.csv

You need to create a file and put addresses in it, for example(addresses.txt)


If you have a large number of addresses, you can split the file using this script.

$split.py

usage :

$python split.py addresses.txt 200

You can change the number of split lines(200) as you want

anyway, Let's choose this address

$1HXSnvNGK8oYQCyLDkpHNZ2sWPvFsYQcFU

1• collecting transactions

Raw transactions containing values and signatures

$fetch_raw_txs.py

This script collects raw transactions from a target address.

usage :

$python fetch_raw_txs.py -a 1HXSnvNGK8oYQCyLDkpHNZ2sWPvFsYQcFU --output results.csv --rawtxt rawtxs.txt
$python fetch_raw_txs.py -a 1HXSnvNGK8oYQCyLDkpHNZ2sWPvFsYQcFU --output results.csv --rawtxt rawtxs.txt --resume --append

rawtxs.txt is file that contains raw transactions is automatically generated by script

fetch_state.json is state file automatically generated by script

You can use command (--resume --append) To continue collecting transactions where left off

$frt_ultra.py

This script like the first one, but with advanced options.

For example, we have this address

$1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

This address has over 52,000 transactions, and that's a large number, Let's say you only want the 100 oldest transactions

First, you will enter this explorer

$https://bitcoin.atomicwallet.io/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

This explorer allows you to browse all transactions, even if there are many, without loading each transaction into a very long sequence.

Each page contains 25 transactions, You will go to the last page, for example, page 2096

Then calculate the number of transactions you want to collect. For example

100÷25=4

1000÷25=40

10000÷25=400

Then subtract a number of pages from the total number.

2096-40=2056

usage :

$python frt_ultra.py -a 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa --start-page 2056 --end-page 2096
$python frt_ultra.py -a 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa --start-page 2015 --end-page 2055 --resume --append

(--resume --append) command to continue collecting

2• analyze

Analyzing transactions to extract values used to calculate private key

$analyze_txs_enhanced.py

This is script that analyzes

usage :

$python analyze_txs_enhanced.py rawtxs.txt

This script will generate file named "der_full_summary.csv" containing values.

The file size can be so large that it is unreadable (file size depends on the analysis; for example, analyzing many transactions, such as 10,000 transactions, might produce a file size of 10+ GB).

You can use this script

$cut_r2.py

This script should be in the same folder as the csv file.

script will read csv file and extract all the lines in which "r" is repeated.

usage :

$python cut_r2.py

Then you can change csv file name to "der_full_summary.csv" to continue working

$compute_z.py

This script calculates z value

usage :

$python compute_z.py --input der_full_summary.csv --output der_with_z.csv --fetch-prevouts

The script will create a file named "der_with_z.csv". This file is required to calculate the private key.

Additions :

$ate_ultra.py

This script similar to analysis script, but with additional features such as sorting signatures according to protocol.

usage :

$python ate_ultra.py rawtxs.txt

$ext_schnorr_extras.py

This script extracts additional information for Schnorr Protocol

usage :

$python ext_schnorr_extras.py rawtxs.txt --fetch-prev

3• computing private key

We will use "der_with_z.csv" file generated by command

$python compute_z.py --input der_full_summary.csv --output der_with_z.csv --fetch-prevouts

because it contains all the values required to calculate the private key.

Required values :

repeated r value (r_hex In CSV file)

s value for each signature (s_hex In CSV file) (We need the value of the first and second signatures. If there are more than two signatures, you can switch between them)

z value for each signature (z_mod_n In CSV file) (Value of the first and second signatures)

The values must be integers.

z values (z_mod_n) is already integer

You must convert (r-s1-s2) values from Hex to an integer

You can use this script

$hex_to_number.py

Create file named "hex.txt" and Write values in it, One line for each value

script will convert values and write them to new file.

usage :

$python hex_to_number.py hex.txt

for example (1HXSnvNGK8oYQCyLDkpHNZ2sWPvFsYQcFU)

When analyzing the transactions of this address, we will find four instances (four signatures) of r repetition (one r value - four s value - four z value)

We will use values from the first and second signatures :

repeated r: hex(00cabc3692f1f7ba75a8572dc5d270b35bcc00650534f6e5ecd6338e55355454d5) int(91699739317935258627372771550459504326006289891191381848862551863464593478869)

s1: hex(00f65bfc44435a91814c142a3b8ee288a9183e6a3f012b84545d1fe334ccfac25e) int(111431484914827310314108809136597661506085346855505784425577929088113412063838)

s2: hex(00b584c5e2f26eaac9510307f466d13f8d4e8f57b1323cc4151ff6ffeb6747ca9b) int(82103215168631327946455936234377737221280608082064931975396899914217832303259)

z1: int(70121596733354710270739379126478863332897631323035990573894949033544740983882)

z2: int(42691526897907875236967398205101700537962275948723679969547592971981809076177)

$compute_x.py

This script calculates the private key.

Before running it, you must open it with a text editor and change the values (r-s1-s2-z1-z2) (Do not change n value) (values must be integers)

usage :

$python compute_x.py

script will print the results

for example:

s_diff = 29328269746195982367652872902219924284804738773440852450181029173895579760579
z_diff = 27430069835446835033771980921377162794935355374312310604347356061562931907705
k (decimal) = 12345678
k (hex) = 0xbc614e
x (decimal) = 36985158630392181731692032973660058930135418234446520253368071243468798761122
x (hex) = 0x51c4dba2c28fc89b208550477a514c87f9d0db0354f03b7c61f08c0a0e3118a2
verification ok: True

x (hex) is the private key

To convert x(hex) to WIF, use this script.

$wif.py

Create file named "xhex.txt" and place it in the same folder, then write x(hex) values in it

script will read file and produce WIF (compressed / uncompressed) With all possibilities with derivatives for each type of address(p2pkh / p2sh / p2wpkh / p2tr), along with a balance check.

usage :

$python wif.py --file xhex.txt --out mywifs.csv

file named "mywifs.csv" will be produced containing the results.

for example:

$5JSJG3nX6z1rsfZ9EZTtbi4qy82TzjGLBpyPzGm7hPRazzrqYzA

This is WIF(uncompressed - p2pkh)to 1HXSnvNGK8oYQCyLDkpHNZ2sWPvFsYQcFU

Additions :

$sc_r.py

This script calculates private key for the schnorr protocol.

usage :

python sc_r.py \
--Rx 0a1b2c3d4e5f60718293a4b5c6d7e8f90123456789abcdef0123456789abcdef \
--Px 1f2e3d4c5b6a79880796a5b4c3d2e1f0a9b8c7d6e5f40123456789abcdef0123 \
--s1 0x8a3f1b2c4d5e6f7091a2b3c4d5e6f7089a1b2c3d4e5f60123456789abcdef012 \
--m1 "hello world" \
--s2 0x7b2e3c4d5f6a7b8091a2b3c4d5e6f70123456789abcdef0123456789abcdef01 \
--m2 "other message"

Change the values

It will print the results

For example :

=== Result ===
e1 = 108970234477436902694766334568020749912403966361468773267923272186995557531266e2 = 66856546383303793989981220542885447886729718496899420254699013163356773868462
s1 = 62530672011108711400438125813195380086512239951027680111811469263325183799314
s2 = 55716171531466744293207597776544084512684920955164725164723036609180125228801
s_diff (s1-s2 mod n) = 6814500479641967107230528036651295573827318995862954947088432654145058570513
e_diff (e1-e2 mod n) = 42113688094133108704785114025135302025674247864569353013224259023638783662804
Recovered private key x (decimal): 47206142724068971842463861168325724021122544036124670454439260535612937450174
Recovered private key x (hex) : 0x685dbadd6c6726922fd9f2b703c7763b4cb00c7078fea84179664a7c0eb5b2be
WIF (mainnet, compressed): KziatDAHb89WXx8xB8uUbAAJ62LpDkGGpbv465vGHfpPzYGcddoQ
WIF (mainnet, uncompressed): 5JcFUTmhTmDMHXcnaZbzubhd3VrMDQPwngBD2c6iynx9PCyXBC1

Support the Project :

If you find this project useful or it helped you in any way, consider supporting me!

Donate :

BTC

$bc1qtxctgmaxwh73h22h862epj3a7yc3tdl2j45aep