Skip to content

Commit

Permalink
v 0.10.0, derivation path as a range
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGorny committed Feb 22, 2021
1 parent 61d3b29 commit 159d425
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 19 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,22 @@ Configuration file example (seed with 6 words, one word unknown, known possible
pitch
hill


</ol>

It is possible to specify the derivation path as a range. For example "m/0/0-4" if you want to launch search on the first five addresses or "m/0/1-2'" if you want to search second and third hardened addresses.
Example of search with a range:

ONE_UNKNOWN
bc1qg3m687gpwljqnzja233sf99aex79cmwr5ewhxh
6
brother
canal
remove
pitch
hill
m/0/2-7'


Contact
-------
Contact email: [email protected]
Expand Down
6 changes: 3 additions & 3 deletions examples/example5.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
ONE_UNKNOWN
#all together - hardened P2WPKH, 4th address the path
bc1qg3m687gpwljqnzja233sf99aex79cmwr5ewhxh, P2WPKH
#all together - hardened P2WPKH, 4th address of the path, search in range
bc1qg3m687gpwljqnzja233sf99aex79cmwr5ewhxh
6
brother
canal
remove
pitch
hill
m/0/3'
m/0/2-7'
28 changes: 28 additions & 0 deletions examples/example_17.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#example with BIP84
ONE_UNKNOWN
bc1qd4fe8fdkm666sl3nnx88rd8wugl07lft8mfhjs
24
twelve
early
treat
random
theme
belt
display
impulse
rookie
dignity
real
wedding
dose
situate
leisure
idle
river
knife
december
betray
economy
cloth
mad
m/84'/0'/0'/0/0-6
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.pawelgorny</groupId>
<artifactId>lostword</artifactId>
<version>0.9.0</version>
<version>0.10.0</version>
<packaging>jar</packaging>

<dependencies>
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/com/pawelgorny/lostword/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public final class Configuration {
private List<String> WORDS;
private List<List<String>> WORDS_POOL;
private int DPaccount = 0;
private int DPaddress = 0;
private int DPaddress = -1;
private int DPaddressMax = -1;
private boolean DPhard = false;
private Script.ScriptType DBscriptType = Script.ScriptType.P2PKH;
private int knownStart = 0;
Expand Down Expand Up @@ -95,9 +96,25 @@ private void parsePath(String path) {
String[] dpath = path.replaceAll("'", "").split("/");
try {
Integer.parseInt(dpath[dpath.length-2]);
Integer.parseInt(dpath[dpath.length-1]);
DPaccount = Integer.parseInt(dpath[dpath.length-2]);
DPaddress = Integer.parseInt(dpath[dpath.length-1]);
try {
Integer.parseInt(dpath[dpath.length - 1]);
}catch (Exception e){
if (dpath[dpath.length - 1].contains("-")){
String[] dpatchAddress = dpath[dpath.length - 1].replaceAll(" ","").split("-");
if (dpatchAddress.length!=2){
parsePath(this.DEFAULT_PATH);
}
Integer.parseInt(dpatchAddress[0]);
Integer.parseInt(dpatchAddress[1]);
DPaddress = Integer.parseInt(dpatchAddress[0]);
DPaddressMax = Integer.parseInt(dpatchAddress[1]);
}
}
if (getDPaddress()==-1) {
DPaddress = Integer.parseInt(dpath[dpath.length - 1]);
DPaddressMax = DPaddress;
}
DPhard = path.endsWith("'");
derivationPath = new ArrayList<>(5);
boolean pathProvided = dpath.length>3;
Expand Down Expand Up @@ -141,6 +158,10 @@ public int getDPaddress() {
return DPaddress;
}

public int getDPaddressMax() {
return DPaddressMax;
}

public boolean isDPhard() {
return DPhard;
}
Expand Down
47 changes: 36 additions & 11 deletions src/main/java/com/pawelgorny/lostword/Worker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import com.pawelgorny.lostword.util.PBKDF2SHA512;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Utils;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.HDDerivationException;
import org.bitcoinj.crypto.HDKeyDerivation;
import org.bitcoinj.crypto.MnemonicException;
import org.bitcoinj.crypto.*;
import org.bitcoinj.script.Script;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.macs.HMac;
Expand Down Expand Up @@ -86,15 +83,43 @@ protected boolean check(final List<String> mnemonic, HMac SHA512DIGEST, MessageD
return false;
}
byte[] seed = PBKDF2SHA512.derive(Utils.SPACE_JOINER.join(mnemonic).getBytes(StandardCharsets.UTF_8), SALT, 2048, 64);
DeterministicKey deterministicKey = createMasterPrivateKey(seed, SHA512DIGEST==null?this.SHA_512_DIGEST:SHA512DIGEST);
for (int i=0; i<configuration.getDerivationPath().size(); i++){
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, configuration.getDerivationPath().get(i));
boolean result;
int addressToWork = configuration.getDPaddress();
int sizeM1=configuration.getDerivationPath().size()-1;
while (addressToWork<=configuration.getDPaddressMax()){
DeterministicKey deterministicKey = createMasterPrivateKey(seed, SHA512DIGEST==null?this.SHA_512_DIGEST:SHA512DIGEST);
for (int i=0; i<configuration.getDerivationPath().size(); i++){
if (sizeM1==i) {
if (addressToWork==configuration.getDPaddress()) {
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, configuration.getDerivationPath().get(i));
}else{
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(addressToWork, configuration.isDPhard()));
}
}else{
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, configuration.getDerivationPath().get(i));
}
}
if (configuration.getDBscriptType().equals(Script.ScriptType.P2WPKH)){
result = Address.fromKey(configuration.getNETWORK_PARAMETERS(), deterministicKey, Script.ScriptType.P2WPKH).equals(configuration.getSegwitAddress());
}else {
result = Address.fromKey(configuration.getNETWORK_PARAMETERS(), deterministicKey, configuration.getDBscriptType()).equals(configuration.getLegacyAddress());
}
if (result){
displayRealDerivationPath(addressToWork);
return true;
}
addressToWork++;
}
if (configuration.getDBscriptType().equals(Script.ScriptType.P2WPKH)){
return Address.fromKey(configuration.getNETWORK_PARAMETERS(), deterministicKey, Script.ScriptType.P2WPKH).equals(configuration.getSegwitAddress());
}else {
return Address.fromKey(configuration.getNETWORK_PARAMETERS(), deterministicKey, configuration.getDBscriptType()).equals(configuration.getLegacyAddress());
return false;
}

private void displayRealDerivationPath(int a){
String dp = "m/";
for (int i=0; i<configuration.getDerivationPath().size()-1; i++){
dp+=configuration.getDerivationPath().get(i).toString().replace('H','\'')+"/";
}
dp+=a+(configuration.isDPhard()?"'":"");
System.out.println("Found address on the derivation path "+dp);
}

protected boolean checksumCheck(final List<String> mnemonic, MessageDigest sha256){
Expand Down

0 comments on commit 159d425

Please sign in to comment.