Skip to content

Commit

Permalink
Refactor and improve secrets file.
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardladenthin committed Mar 12, 2024
1 parent b27db55 commit 82463c6
Show file tree
Hide file tree
Showing 19 changed files with 392 additions and 74 deletions.
56 changes: 56 additions & 0 deletions examples/config_Find_SecretsFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"command": "Find",
"finder" : {
"consumerJava" : {
"lmdbConfigurationReadOnly" : {
"lmdbDirectory" : "lmdb",
"useProxyOptimal" : true,
"logStatsOnInit" : true,
"logStatsOnClose" : false
},
"threads" : 4,
"delayEmptyConsumer" : 50,
"printStatisticsEveryNSeconds" : 10,
"queueSize" : 4,
"runtimePublicKeyCalculationCheck" : false,
"enableVanity" : false,
"vanityPattern" : "1[Ee][Mm][Ii][Ll].*"
},
"producerOpenCL" : [
],
"producerJavaSecretsFiles" : [
{
"files" : [
"fileContainingSecrets_BIG_INTEGER.txt"
],
"secretFormat" : "STRING_DO_SHA256",
"logSecretBase" : true,
"gridNumBits" : 0
},
{
"files" : [
"fileContainingSecrets_DUMPED_RIVATE_KEY.txt"
],
"secretFormat" : "STRING_DO_SHA256",
"logSecretBase" : true,
"gridNumBits" : 0
},
{
"files" : [
"fileContainingSecrets_SHA256.txt"
],
"secretFormat" : "STRING_DO_SHA256",
"logSecretBase" : true,
"gridNumBits" : 0
},
{
"files" : [
"fileContainingSecrets_STRING_DO_SHA256.txt"
],
"secretFormat" : "STRING_DO_SHA256",
"logSecretBase" : true,
"gridNumBits" : 0
}
]
}
}
14 changes: 14 additions & 0 deletions examples/run_Find_SecretsFile.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
rem start /low java ^
java ^
--add-opens java.base/java.lang=ALL-UNNAMED ^
--add-opens java.base/java.io=ALL-UNNAMED ^
--add-opens java.base/java.nio=ALL-UNNAMED ^
--add-opens java.base/jdk.internal.ref=ALL-UNNAMED ^
--add-opens java.base/sun.nio.ch=ALL-UNNAMED ^
--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED ^
-Xms512M ^
-Xmx16G ^
-Dlogback.configurationFile=logbackConfiguration.xml ^
-jar ^
bitcoinaddressfinder-1.1.0-SNAPSHOT-jar-with-dependencies.jar ^
config_Find_SecretsFile.js >> log_Find_SecretsFile.txt 2>&1
3 changes: 3 additions & 0 deletions examples/secrets/fileContainingSecrets_BIG_INTEGER.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
72155939486846849509759369733266486982821795810448245423168957390607644363272
39929263256442288830290225612580366403172818928633701045115663441379782969864
42379586058257162021782620237913525000692985364990081801945649219990416465578
3 changes: 3 additions & 0 deletions examples/secrets/fileContainingSecrets_DUMPED_RIVATE_KEY.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
5K2YUVmWfxbmvsNxCsfvArXdGXm7d5DC9pn4yD75k2UaSYgkXTh
5JVAXLpkZ21svEzwyimMHn5hAkWNqJq8uGxqUqcRrNb8F4Csp8V
5JXYuGrwSbyp8sKBmiLcvokqSnxALPjKWQMPJXZYyBWKof7c2pk
3 changes: 3 additions & 0 deletions examples/secrets/fileContainingSecrets_SHA256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
58472980a1d3449939eadc2652370972d5007fa9c059ce84fb3ab98f544e4a08
5db1fee4b5703808c48078a76768b155b421b210c0761cd6a5d223f4d99f1eaa
3 changes: 3 additions & 0 deletions examples/secrets/fileContainingSecrets_STRING_DO_SHA256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test
test with space
1337
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void waitTillProducerNotRunning() {
}

public BigInteger createSecretBase(CProducer cProducer, BigInteger secret, boolean logSecretBase) {
BigInteger secretBase = cProducer.killBits(secret);
BigInteger secretBase = keyUtility.killBits(secret, cProducer.getKillBits());

if(logSecretBase) {
logger.info("secretBase: " + org.bouncycastle.util.encoders.Hex.toHexString(secretBase.toByteArray()) + "/" + cProducer.gridNumBits);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public KeyUtility(NetworkParameters networkParameters, ByteBufferUtility byteBuf
this.networkParameters = networkParameters;
this.byteBufferUtility = byteBufferUtility;
}

public BigInteger killBits(BigInteger bigInteger, BigInteger killBits) {
return bigInteger.andNot(killBits);
}

/**
* Require networkParameters.
Expand Down
36 changes: 21 additions & 15 deletions src/main/java/net/ladenthin/bitcoinaddressfinder/ProducerJava.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

public class ProducerJava extends AbstractProducer {

private final CProducerJava producerJava;
protected final CProducerJava producerJava;

public ProducerJava(CProducerJava producerJava, AtomicBoolean shouldRun, Consumer consumer, KeyUtility keyUtility, Random random) {
super(shouldRun, consumer, keyUtility, random);
Expand All @@ -38,32 +38,38 @@ public void initProducer() {

@Override
public void produceKeys() {
BigInteger secret = null;
BigInteger secret = keyUtility.createSecret(producerJava.privateKeyMaxNumBits, random);
processSecret(secret);
}

protected void processSecret(BigInteger secret) {
try {
secret = keyUtility.createSecret(producerJava.privateKeyMaxNumBits, random);
if (PublicKeyBytes.isInvalid(secret)) {
return;
}

final BigInteger secretBase = createSecretBase(producerJava, secret, producerJava.logSecretBase);

PublicKeyBytes[] publicKeyBytesArray = new PublicKeyBytes[producerJava.getWorkSize()];
for (int i = 0; i < publicKeyBytesArray.length; i++) {
// create uncompressed
BigInteger gridSecret = calculateSecretKey(secretBase, i);
if (PublicKeyBytes.isInvalid(gridSecret)) {
publicKeyBytesArray[i] = PublicKeyBytes.INVALID_KEY_ONE;
continue;
}
publicKeyBytesArray[i] = PublicKeyBytes.fromPrivate(gridSecret);
}

PublicKeyBytes[] publicKeyBytesArray = createGrid(secretBase);
consumer.consumeKeys(publicKeyBytesArray);
} catch (Exception e) {
logErrorInProduceKeys(e, secret);
}
}

protected PublicKeyBytes[] createGrid(final BigInteger secretBase) {
PublicKeyBytes[] publicKeyBytesArray = new PublicKeyBytes[producerJava.getWorkSize()];
for (int i = 0; i < publicKeyBytesArray.length; i++) {
// create uncompressed
BigInteger gridSecret = calculateSecretKey(secretBase, i);
if (PublicKeyBytes.isInvalid(gridSecret)) {
publicKeyBytesArray[i] = PublicKeyBytes.INVALID_KEY_ONE;
continue;
}
publicKeyBytesArray[i] = PublicKeyBytes.fromPrivate(gridSecret);
}
return publicKeyBytesArray;
}

@Override
public void releaseProducers() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProducerJavaSecretsFiles extends AbstractProducer {
public class ProducerJavaSecretsFiles extends ProducerJava {

private final Logger logger = LoggerFactory.getLogger(ProducerJavaSecretsFiles.class);

Expand All @@ -38,7 +38,7 @@ public class ProducerJavaSecretsFiles extends AbstractProducer {
private final ReadStatistic readStatistic = new ReadStatistic();

public ProducerJavaSecretsFiles(CProducerJavaSecretsFiles producerJavaSecretsFiles, AtomicBoolean shouldRun, Consumer consumer, KeyUtility keyUtility, Random random) {
super(shouldRun, consumer, keyUtility, random);
super(producerJavaSecretsFiles, shouldRun, consumer, keyUtility, random);
this.producerJavaSecretsFiles = producerJavaSecretsFiles;
}

Expand Down Expand Up @@ -86,17 +86,4 @@ private void logProgress() {
@Override
public void releaseProducers() {
}

private void processSecret(BigInteger secret) {
try {
if (PublicKeyBytes.isInvalid(secret)) {
return;
}
PublicKeyBytes publicKeyBytes = PublicKeyBytes.fromPrivate(secret);
PublicKeyBytes[] publicKeyBytesArray = new PublicKeyBytes[]{publicKeyBytes};
consumer.consumeKeys(publicKeyBytesArray);
} catch (Exception e) {
logErrorInProduceKeys(e, secret);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ public class PublicKeyBytes {

public static final int ONE_COORDINATE_NUM_BYTES = 32;
public static final int TWO_COORDINATES_NUM_BYTES = ONE_COORDINATE_NUM_BYTES * 2;

/**
* Computes the maximum permissible length for an array intended to store pairs of coordinates within a 32-bit system.
* This constant represents the upper limit on array length, factoring in the memory constraint imposed by the maximum
* integer value addressable in Java ({@link Integer#MAX_VALUE}) and the storage requirement for two coordinates.
* <p>
* The calculation divides {@link Integer#MAX_VALUE} by the number of bytes needed to store two coordinates,
* as defined by {@link PublicKeyBytes#TWO_COORDINATES_NUM_BYTES}, ensuring the array's indexing does not surpass
* Java's maximum allowable array length.
* </p>
*/
public static final int MAXIMUM_TWO_COORDINATES_ARRAY_LENGTH = (int)(Integer.MAX_VALUE / PublicKeyBytes.TWO_COORDINATES_NUM_BYTES);

/**
* Determines the minimum number of bits required to address the maximum array length for storing coordinate pairs.
* This value is crucial for efficiently allocating memory without exceeding the 32-bit system's limitations.
* <p>
* The calculation employs a bit manipulation strategy to find the exponent of the nearest superior power of 2
* capable of accommodating the maximum array length. By decrementing the maximum array length by 1 and
* calculating 32 minus the count of leading zeros in the decremented value, we obtain the closest superior power of 2.
* This technique, derived from a common bit manipulation trick (source: https://stackoverflow.com/questions/5242533/fast-way-to-find-exponent-of-nearest-superior-power-of-2),
* ensures the calculated bit count represents the smallest possible number that can address all potential array indices
* without breaching the 32-bit address space limitation.
* </p>
*/
public static final int BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY = PublicKeyBytes.MAXIMUM_TWO_COORDINATES_ARRAY_LENGTH == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(PublicKeyBytes.MAXIMUM_TWO_COORDINATES_ARRAY_LENGTH - 1) - 1;

public static final int PARITY_BYTES_LENGTH = 1;

public static final int LAST_Y_COORDINATE_BYTE_INDEX = PublicKeyBytes.PARITY_BYTES_LENGTH + PublicKeyBytes.TWO_COORDINATES_NUM_BYTES - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ public class CProducer {
*/
private BigInteger killBits;

public static final int MAX_GRID_NUM_BITS = 24;

/**
* (2<sup>{@code maxNumBits}</sup> - 1) can be set to a lower value to improve a search on specific ranges (e.g. the puzzle transaction https://privatekeys.pw/puzzles/bitcoin-puzzle-tx ).
* {@code 1} can't be tested because {@link ECKey#fromPrivate} throws an {@link IllegalArgumentException}.
Expand All @@ -38,9 +36,9 @@ public class CProducer {
public int privateKeyMaxNumBits = PublicKeyBytes.PRIVATE_KEY_MAX_NUM_BITS;

/**
* Range: {@code 1} (inclusive) to {@link #MAX_GRID_NUM_BITS} (inclusive).
* Range: {@code 0} (inclusive) to {@link PublicKeyBytes#BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY} (inclusive).
*/
public int gridNumBits = 8;
public int gridNumBits = 0;

/**
* Enable the log output for the secret address.
Expand All @@ -58,26 +56,13 @@ public BigInteger getKillBits() {
return killBits;
}

public BigInteger killBits(BigInteger bigInteger) {
return bigInteger.andNot(getKillBits());
}

public void assertGridNumBitsCorrect() {
{
// ensure the constant MAX_GRID_NUM_BITS is set correct
int maximumWorkSize = (int)(Integer.MAX_VALUE / PublicKeyBytes.TWO_COORDINATES_NUM_BYTES);
// https://stackoverflow.com/questions/5242533/fast-way-to-find-exponent-of-nearest-superior-power-of-2
int numBitsMaximum = maximumWorkSize == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(maximumWorkSize - 1);

if (MAX_GRID_NUM_BITS > numBitsMaximum) {
throw new IllegalArgumentException("MAX_GRID_NUM_BITS is too high for 32 bit memory allocation.");
}
if (gridNumBits < 0) {
throw new IllegalArgumentException("gridNumBits must higher than 0.");
}

if (gridNumBits > MAX_GRID_NUM_BITS) {
throw new IllegalArgumentException("gridNumBits must be lower or equal than " + MAX_GRID_NUM_BITS + ".");
if (gridNumBits > PublicKeyBytes.BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY) {
throw new IllegalArgumentException("gridNumBits must be lower or equal than " + PublicKeyBytes.BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY + ".");
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.ArrayList;
import java.util.List;

public class CProducerJavaSecretsFiles extends CProducer {
public class CProducerJavaSecretsFiles extends CProducerJava {
/**
* The list of strings files which should be read.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@
package net.ladenthin.bitcoinaddressfinder.configuration;

public enum CSecretFormat {
/**
* Also known as a brainwallet. A string is hashed using SHA256 and used as the private key.
* e.g.:
* <pre>
* test
* test with space
* 1337
* </pre>
*/
STRING_DO_SHA256,

/**
* Represents a big integer.
Expand All @@ -41,6 +31,17 @@ public enum CSecretFormat {
*/
BIG_INTEGER,

/**
* Also referred to as WiF (Wallet Import Format).
* e.g.:
* <pre>
* 5K2YUVmWfxbmvsNxCsfvArXdGXm7d5DC9pn4yD75k2UaSYgkXTh
* 5JVAXLpkZ21svEzwyimMHn5hAkWNqJq8uGxqUqcRrNb8F4Csp8V
* 5JXYuGrwSbyp8sKBmiLcvokqSnxALPjKWQMPJXZYyBWKof7c2pk
* </pre>
*/
DUMPED_RIVATE_KEY,

/**
* A HEX-encoded SHA256 string. This might already be the hashed brainwallet.
* e.g.:
Expand All @@ -53,13 +54,13 @@ public enum CSecretFormat {
SHA256,

/**
* Also referred to as WiF (Wallet Import Format).
* e.g.:
* Also known as a brainwallet. A string is hashed using SHA256 and used as the private key.
* e.g.:
* <pre>
* 5K2YUVmWfxbmvsNxCsfvArXdGXm7d5DC9pn4yD75k2UaSYgkXTh
* 5JVAXLpkZ21svEzwyimMHn5hAkWNqJq8uGxqUqcRrNb8F4Csp8V
* 5JXYuGrwSbyp8sKBmiLcvokqSnxALPjKWQMPJXZYyBWKof7c2pk
* test
* test with space
* 1337
* </pre>
*/
DUMPED_RIVATE_KEY
STRING_DO_SHA256
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public static Object[][] lmdbIncreaseSize() {
@DataProvider
public static Object[][] bitSizesLowerThan25() {
// if the constant was changed, the dataprovider and its test must be changed also
if(CProducerOpenCL.MAX_GRID_NUM_BITS != 24) {
// this constant can not change because of the maximum size in 32-bit systems
if(PublicKeyBytes.BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY != 24) {
throw new IllegalStateException("Adapt data provider.");
}

Expand Down Expand Up @@ -164,7 +165,7 @@ public static Object[][] bitSizesLowerThan25() {
{21},
{22},
{23},
{CProducerOpenCL.MAX_GRID_NUM_BITS}
{PublicKeyBytes.BIT_COUNT_FOR_MAX_COORDINATE_PAIRS_ARRAY}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,24 @@ public void bigIntegerToBytes_maxPrivateKeyGiven_returnWithoutLeadingZeros() thr
assertThat(arrayWithLeadingZero, is(equalTo(maxPrivateKey)));
}
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="killBits">
@Test
public void killBits_valueWithAllBitsSetGiven_bitsKilled() throws IOException {
// act
BigInteger secret = new KeyUtility(null, new ByteBufferUtility(false)).killBits(BigInteger.valueOf(63L), BigInteger.valueOf(5L));

// assert
assertThat(secret, is(equalTo(BigInteger.valueOf(58))));
}

@Test
public void killBits_valueWithNotAllBitsSetGiven_bitsKilled() throws IOException {
// act
BigInteger secret = new KeyUtility(null, new ByteBufferUtility(false)).killBits(BigInteger.valueOf(62L), BigInteger.valueOf(5L));

// assert
assertThat(secret, is(equalTo(BigInteger.valueOf(58))));
}
// </editor-fold>
}
Loading

0 comments on commit 82463c6

Please sign in to comment.