package no.ntnu.item.threads;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import no.ntnu.item.bruteforce.BruteForce;
import de.rtner.security.auth.spi.PBKDF2Engine;
import de.rtner.security.auth.spi.PBKDF2Parameters;
public class BruteForceThread implements Runnable {
public Thread thread;
private String t_word;
private SecretKey t_key;
private byte[] t_plain;
private byte[] t_salt;
private byte[] t_cipher;
public BruteForceThread() {
}
public BruteForceThread(String id) {
synchronized (BruteForce.salt) {
t_salt = BruteForce.salt;
}
synchronized (BruteForce.cipher) {
t_cipher = BruteForce.cipher;
}
t_key = null;
t_plain = null;
thread = new Thread(this, id);
thread.start();
}
@Override
public void run() {
synchronized (BruteForce.words) {
try {
BruteForce.words.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (true) {
synchronized (BruteForce.words) {
if (BruteForce.words.size() == 0)
break;
t_word = new String(BruteForce.words.remove(0));
}
if (checkWord(t_word)) {
BruteForce.time = (System.currentTimeMillis() - BruteForce.start) / 1000.0;
BruteForce.printSuccess(t_word);
BruteForce.found = true;
break;
}
}
if (!BruteForce.found && Thread.activeCount() == 2) {
BruteForce.printFail();
}
}
public boolean checkWord(String word) {
this.setKey(word);
t_plain = symECBDecrypt(t_cipher, t_key);
// 68 = char D and indicate correct decryption of first byte
if (t_plain != null && t_plain[0] == 68) {
// If first byte is correct: look at plaintext pattern
String[] parts = new String(t_plain).split(":");
String[] parts2 = new String(t_plain).split("|");
if (parts.length == 4 && parts2.length == 5) {
return true;
}
}
return false;
}
public void setKey(String password) {
PBKDF2Parameters param = new PBKDF2Parameters("HmacSHA256", "UTF-8",
t_salt, 4096);
PBKDF2Engine engine = new PBKDF2Engine(param);
param.setDerivedKey(engine.deriveKey(password, 16));
t_key = new SecretKeySpec(param.getDerivedKey(), "AES");
}
public synchronized byte[] symECBDecrypt(byte[] cipherText, SecretKey key) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
BruteForce.words_read++;
return cipher.doFinal(cipherText);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
if (e.getMessage().equals("Illegal key size or default parameter")) {
e.printStackTrace();
System.out
.println("\nERROR: Have you installed the Java(TM) Cryptography Extension (JCE) Jurisdiction Policy Files?");
System.exit(1);
}
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
}
return null;
}
}