diff --git a/examples/example_26.conf b/examples/example_26.conf
new file mode 100644
index 0000000..d86e248
--- /dev/null
+++ b/examples/example_26.conf
@@ -0,0 +1,9 @@
+PRINT_SEEDS
+anyText
+6
+brother
+canal
+?
+remove
+pitch
+hill
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index eba09f7..4458614 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.pawelgorny
lostword
- 0.15.0
+ 0.16.0
jar
diff --git a/src/main/java/com/pawelgorny/lostword/Configuration.java b/src/main/java/com/pawelgorny/lostword/Configuration.java
index cdefa8f..7d08c4e 100644
--- a/src/main/java/com/pawelgorny/lostword/Configuration.java
+++ b/src/main/java/com/pawelgorny/lostword/Configuration.java
@@ -96,7 +96,7 @@ private void parseScript(String targetAddress) {
this.coin = Configuration.ETHEREUM;
}
}
- if (!WORK.ONE_UNKNOWN_CHECK_ALL.equals(work) && !WORK.PERMUTATION.equals(work)){
+ if (!WORK.ONE_UNKNOWN_CHECK_ALL.equals(work) && !WORK.PERMUTATION.equals(work) && !WORK.PRINT_SEEDS.equals(work)){
if (this.ethereumAddress==null){
switch (getDBscriptType()){
case P2PKH:
diff --git a/src/main/java/com/pawelgorny/lostword/Main.java b/src/main/java/com/pawelgorny/lostword/Main.java
index c2edad9..478d2e9 100644
--- a/src/main/java/com/pawelgorny/lostword/Main.java
+++ b/src/main/java/com/pawelgorny/lostword/Main.java
@@ -88,7 +88,7 @@ private static Configuration readConfiguration(String file) {
}
words.add(line);
}
- }else if (WORK.KNOWN_POSITION.equals(work) || WORK.PERMUTATION.equals(work) || WORK.PERMUTATION_CHECK.equals(work)){
+ }else if (WORK.KNOWN_POSITION.equals(work) || WORK.PERMUTATION.equals(work) || WORK.PERMUTATION_CHECK.equals(work)|| WORK.PRINT_SEEDS.equals(work)){
if (words.size() == size) {
path = line;
}else if (words.size() < size) {
@@ -153,7 +153,7 @@ private static Configuration readConfiguration(String file) {
if (WORK.POOL.equals(work)){
configuration.setWORDS_POOL(wordsPool);
}
- if (WORK.KNOWN_POSITION.equals(work) && words.get(size-1).equalsIgnoreCase("?")){
+ if ((WORK.KNOWN_POSITION.equals(work)||WORK.PRINT_SEEDS.equals(work)) && words.get(size-1).equalsIgnoreCase("?")){
for (int s=9, b=3; s<=24; s+=3, b++){
if (s==size){
configuration.setMissingChecksum(true);
diff --git a/src/main/java/com/pawelgorny/lostword/WORK.java b/src/main/java/com/pawelgorny/lostword/WORK.java
index ceff30b..6a9699d 100644
--- a/src/main/java/com/pawelgorny/lostword/WORK.java
+++ b/src/main/java/com/pawelgorny/lostword/WORK.java
@@ -1,5 +1,6 @@
package com.pawelgorny.lostword;
public enum WORK {
- ONE_UNKNOWN, KNOWN_POSITION, ONE_UNKNOWN_CHECK_ALL, POOL, PERMUTATION, PERMUTATION_CHECK
+ ONE_UNKNOWN, KNOWN_POSITION, ONE_UNKNOWN_CHECK_ALL, POOL, PERMUTATION, PERMUTATION_CHECK,
+ PRINT_SEEDS
}
diff --git a/src/main/java/com/pawelgorny/lostword/Worker.java b/src/main/java/com/pawelgorny/lostword/Worker.java
index b61a7f6..0abe843 100644
--- a/src/main/java/com/pawelgorny/lostword/Worker.java
+++ b/src/main/java/com/pawelgorny/lostword/Worker.java
@@ -47,6 +47,8 @@ public class Worker {
private final int CONCAT_LEN_BITS_MINUS_CONCAT_LEN_BITS_DIV_33;
private final int CONCAT_LEN_BITS_MINUS_CONCAT_LEN_BITS_DIV_33__DIV8;
+ protected final List PRINT_SEEDS=new ArrayList<>(0);
+
public Worker(Configuration configuration) {
this.configuration = configuration;
this.CONCAT_LEN_BITS = 11 * configuration.getSIZE();
@@ -84,9 +86,12 @@ public void run() throws InterruptedException, MnemonicException {
case PERMUTATION:
worker = new WorkerPermutation(configuration);
break;
+ case PRINT_SEEDS:
+ worker = new WorkerPrintSeeds(configuration);
+ break;
}
System.out.println("--- Starting worker --- "+ SDTF.format(new Date())+" ---");
- if (WORK.PERMUTATION.equals(configuration.getWork())){
+ if (WORK.PERMUTATION.equals(configuration.getWork()) || WORK.PRINT_SEEDS.equals(configuration.getWork())){
worker.run();
System.out.println();
return;
@@ -173,6 +178,21 @@ protected Boolean check(final List mnemonic, HMac SHA512DIGEST, MessageD
return false;
}
+ protected Boolean checkPrint(final List mnemonic, HMac SHA512DIGEST, MessageDigest sha256) throws MnemonicException {
+ if (!checksumCheck(mnemonic, sha256)){
+ return configuration.isMissingChecksum()?null:false;
+ }
+
+ if (Configuration.ETHEREUM.equals(configuration.getCoin())){
+ return checkEthereum(mnemonic);
+ }
+
+ String seed = Utils.SPACE_JOINER.join(mnemonic);
+ System.out.println(seed);
+ PRINT_SEEDS.add(seed);
+ return true;
+ }
+
protected boolean checkEthereum(final List mnemonic) throws MnemonicException {
DeterministicSeed seed = new DeterministicSeed(mnemonic, null, "", System.currentTimeMillis());
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).build();
diff --git a/src/main/java/com/pawelgorny/lostword/WorkerKnownPosition.java b/src/main/java/com/pawelgorny/lostword/WorkerKnownPosition.java
index 1fd7fc1..bbdf8a4 100644
--- a/src/main/java/com/pawelgorny/lostword/WorkerKnownPosition.java
+++ b/src/main/java/com/pawelgorny/lostword/WorkerKnownPosition.java
@@ -16,6 +16,7 @@ public class WorkerKnownPosition extends Worker{
private static int NUMBER_UNKNOWN;
private long start = 0;
+ private long COUNTER = 0L;
public WorkerKnownPosition(Configuration configuration) {
super(configuration);
@@ -109,13 +110,15 @@ private void checkUnknown(int position) throws InterruptedException {
private Boolean processSeed(final List seed, int depth, int positionStartSearch, boolean reporter, HMac SHA_512_DIGEST, MessageDigest SHA_256_DIGEST) throws MnemonicException {
if (NUMBER_UNKNOWN==depth){
Boolean checkResult = check(seed, SHA_512_DIGEST, SHA_256_DIGEST);
+ COUNTER++;
if (checkResult!=null&&checkResult){
System.out.println(seed);
RESULT = new Result(new ArrayList<>(seed));
return true;
}
if (reporter && (System.currentTimeMillis()-start > STATUS_PERIOD)){
- System.out.println(SDTF.format(new Date())+ " Alive!");
+ System.out.println(SDTF.format(new Date())+ " Alive! "+(COUNTER));
+ COUNTER = 0;
start = System.currentTimeMillis();
}
return configuration.isMissingChecksum()?(checkResult==null?false:null):checkResult;
diff --git a/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java b/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
index df6e4dd..6f8ef7b 100644
--- a/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
+++ b/src/main/java/com/pawelgorny/lostword/WorkerPermutationCheck.java
@@ -17,6 +17,7 @@ public class WorkerPermutationCheck extends Worker{
private MessageDigest SHA_256_DIGEST;
private long start = 0;
+ long counter = 0L;
public WorkerPermutationCheck(Configuration configuration) {
super(configuration);
@@ -114,6 +115,9 @@ private boolean checkElements(String[] target, String[] input, HMac LOCAL_SHA_51
List mnemonic = Arrays.asList(target);
try {
boolean result = check(mnemonic, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST);
+ if (REPORTER) {
+ counter++;
+ }
if (result){
RESULT = new Result(mnemonic);
}
@@ -121,7 +125,8 @@ private boolean checkElements(String[] target, String[] input, HMac LOCAL_SHA_51
System.out.println(e.getLocalizedMessage());
}
if (REPORTER && (System.currentTimeMillis()-start > STATUS_PERIOD)){
- System.out.println(SDTF.format(new Date())+ " Alive!");
+ System.out.println(SDTF.format(new Date())+ " Alive! "+counter);
+ counter = 0;
start = System.currentTimeMillis();
}
return (RESULT!=null);
diff --git a/src/main/java/com/pawelgorny/lostword/WorkerPrintSeeds.java b/src/main/java/com/pawelgorny/lostword/WorkerPrintSeeds.java
new file mode 100644
index 0000000..f93d7e2
--- /dev/null
+++ b/src/main/java/com/pawelgorny/lostword/WorkerPrintSeeds.java
@@ -0,0 +1,205 @@
+package com.pawelgorny.lostword;
+
+import org.bitcoinj.crypto.MnemonicException;
+import org.bouncycastle.crypto.macs.HMac;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class WorkerPrintSeeds extends Worker{
+
+ private static int NUMBER_UNKNOWN;
+ private long start = 0;
+ private long COUNTER = 0L;
+
+ public WorkerPrintSeeds(Configuration configuration) {
+ super(configuration);
+ THREADS = 1;
+ }
+
+ public void run() throws InterruptedException, MnemonicException {
+ check();
+ try {
+ FileWriter fileWriter = new FileWriter(this.configuration.getWork().name() + "_result_" + SDTCF.format(new Date()) + ".txt", false);
+ for (String seed:PRINT_SEEDS) {
+ fileWriter.write(seed+"\r\n");
+ }
+ fileWriter.close();
+ } catch (IOException e) {
+ System.out.println("Cannot write to file: " + e.getLocalizedMessage());
+ }
+ }
+
+ private void check() throws MnemonicException, InterruptedException {
+ NUMBER_UNKNOWN = 0;
+ int position = -1;
+ int c=0;
+ for (String word : configuration.getWORDS()){
+ if (Configuration.UNKNOWN_CHAR.equalsIgnoreCase(word)){
+ NUMBER_UNKNOWN++;
+ if (position==-1) {
+ position = c;
+ }
+ }
+ c++;
+ }
+ if (NUMBER_UNKNOWN == 1){
+ checkOne(position);
+ }
+ else{
+ checkUnknown(position);
+ }
+ }
+
+ private int getNextUnknown(int startSearch, List list){
+ for (int p0=startSearch; p0 mnemonic = new ArrayList<>(configuration.getWORDS());
+ List> DICTIONARY = split();
+ int nextPosition = getNextUnknown(1+position, configuration.getWORDS());
+
+ final List SHA_256_DIGESTS= new ArrayList<>(THREADS);
+ final List SHA_512_DIGESTS= new ArrayList<>(THREADS);
+ for (int t=0; t SEED = new LinkedList<>(mnemonic);
+ final List WORDS_TO_WORK = DICTIONARY.get(t);
+ final boolean REPORTER = t==0;
+ final int T_NUMBER=t;
+ executorService.submit(() -> {
+ if (REPORTER) {
+ start = System.currentTimeMillis();
+ }
+ final HMac LOCAL_SHA_512_DIGEST = SHA_512_DIGESTS.get(T_NUMBER);
+ final MessageDigest LOCAL_SHA_256_DIGEST = SHA_256_DIGESTS.get(T_NUMBER);
+ try {
+ int WORKING_POSITION_PLUS = WORKING_POSITION+1;
+ for (int bipPosition = 0; RESULT == null && bipPosition < WORDS_TO_WORK.size(); bipPosition++) {
+ SEED.set(WORKING_POSITION, WORDS_TO_WORK.get(bipPosition));
+ processSeed(SEED, 2, WORKING_POSITION_PLUS, REPORTER, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST);
+ }
+ } catch (Exception e) {
+ Thread.currentThread().interrupt();
+ }
+ latch.countDown();
+ });
+ }
+ latch.await();
+ executorService.shutdown();
+ }
+ }
+
+ private Boolean processSeed(final List seed, int depth, int positionStartSearch, boolean reporter, HMac SHA_512_DIGEST, MessageDigest SHA_256_DIGEST) throws MnemonicException {
+ if (NUMBER_UNKNOWN==depth){
+ Boolean checkResult = checkPrint(seed, SHA_512_DIGEST, SHA_256_DIGEST);
+ COUNTER++;
+ if (checkResult!=null&&checkResult){
+ System.out.println(seed);
+ RESULT = new Result(new ArrayList<>(seed));
+ return true;
+ }
+ if (reporter && (System.currentTimeMillis()-start > STATUS_PERIOD)){
+ System.out.println(SDTF.format(new Date())+ " Alive! "+(COUNTER));
+ COUNTER = 0;
+ start = System.currentTimeMillis();
+ }
+ return configuration.isMissingChecksum()?(checkResult==null?false:null):checkResult;
+ }else{
+ int nextDepth = depth + 1;
+ int position = getNextUnknown(positionStartSearch, seed);
+ if(position == -1){
+ Boolean checkResult = check(seed, SHA_512_DIGEST, SHA_256_DIGEST);
+ if (checkResult!=null&&checkResult){
+ System.out.println(seed);
+ RESULT = new Result(new ArrayList<>(seed));
+ }
+ return false;
+ }
+ int positionStartNextSearch = 0;
+ if (nextDepth > DICTIONARY = split();
+ System.out.println("Checking missing word at position " + (position + 1));
+ Iterator iterator = configuration.getWORDS().iterator();
+ int p = 0;
+ List mnemonic = new ArrayList<>(configuration.getSIZE());
+ for (int i = 0; i < configuration.getSIZE(); i++) {
+ mnemonic.add("");
+ }
+ while (iterator.hasNext()) {
+ String word = iterator.next();
+ if (Configuration.UNKNOWN_CHAR.equalsIgnoreCase(word)){
+ continue;
+ }
+ if (p == position) {
+ p++;
+ }
+ mnemonic.set(p++, word);
+ }
+ final CountDownLatch latch = new CountDownLatch(THREADS);
+ final ExecutorService executorService = Executors.newFixedThreadPool(THREADS);
+ for (int t = 0; t < THREADS; t++) {
+ final int WORKING_POSITION = position;
+ final List WORDS_TO_WORK = DICTIONARY.get(t);
+ final List SEED = new ArrayList<>(mnemonic);
+ executorService.submit(() -> {
+ try {
+ final MessageDigest LOCAL_SHA_256_DIGEST = MessageDigest.getInstance("SHA-256");
+ final HMac LOCAL_SHA_512_DIGEST = createHmacSha512Digest();
+ for (int bipPosition = 0; RESULT == null && bipPosition < WORDS_TO_WORK.size(); bipPosition++) {
+ SEED.set(WORKING_POSITION, WORDS_TO_WORK.get(bipPosition));
+ checkPrint(SEED, LOCAL_SHA_512_DIGEST, LOCAL_SHA_256_DIGEST);
+ }
+ } catch (Exception e) {
+ Thread.currentThread().interrupt();
+ }
+ latch.countDown();
+ });
+ }
+ latch.await();
+ executorService.shutdown();
+ }
+
+}