如何多线程暴力破解java密码程序
How to multi-thread a brute force java password program
我为我的 11 年级计算机科学项目创建了一个程序,我制作了一个 java 密码破解器,可以暴力破解密码。但是,我想获得一些关于如何对我的 java 程序(下面提供的代码)进行多线程处理以加速暴力破解过程的建议。如果它有帮助的话,我是 运行 英特尔的 i7-3770 处理器,它是四核的,但每个内核有 2 个线程,所以一次有 8 个可能的线程。
代码如下:
import java.util.*;
import java.io.*;
class pwcracker
{
public static void main (String[] args)
{
Scanner scan = new Scanner( System.in );
Random rand = new Random();
Runtime.getRuntime().availableProcessors();
String pw, choices, guess;
long tries;
int j, length;
System.out.println("Enter a password that is up to 5 chars and contains no numbers: ");
pw = "" + scan.nextLine();
length = pw.length();
choices = "abcdefghijklmnopqrstuvwxyz";
tries = 0;
guess = "";
System.out.println("Your pw is: " + pw);
System.out.println("The length of your pw is: " + length);
System.out.println("for TEST- Guess: " + guess + "pw :"+pw);
if (guess != pw){
while (guess != pw)
{
j = 0;
guess = "";
while ( j < length )
{
guess = guess + choices.charAt( rand.nextInt ( choices.length() ) );
j = j + 1;
if (guess == pw)
{
System.out.println("Match found, ending loop..");
break;
}
}
System.out.println("2 Guess: " + guess + " pw :"+pw);
tries = tries + 1;
}
}
System.out.println("Here is your password: " + guess);
System.out.println("It took " + tries + " tries to guess it.");
}
}
首先,您想尽可能减少循环中不必要的函数调用。例如 choices.length 可以作为变量存储在内存中,比如 int choice = choice.length。这将优化您的程序,因为每次计算机不必计算长度时,它已经存储在内存中供其使用。
如果您想使用线程化路线,那么我会将其设置为 producer-consumer 算法。在高层,我们有生产者线程创建工作,我们有消费者线程执行工作,我们有一个共享队列对象,我们使用它来将工作单元从生产者转移到消费者。
在你的例子中,由于你的样本 space 相对较小(重复长度为 5 的排列),我将有一个生产者线程。如果您使用下面我的建议,这也将有助于使事情变得简单。 This tutorial 作为您的起点看起来很简单。至于要使用的线程总数,从小处着手,尝试使用不同数量的线程。
我看到您在随机创建字符串以进行检查。但是,由于这会产生大量重复和冗余的检查,因此我建议使用排列。也就是说,您需要长度为 5 的字母表字符的所有排列。我发现这个库可以 combinations and permutations。这将使您无需重复即可获得所有可能的安排。像这样:
// Create the initial vector of 26 elements (alphabet)
ICombinatoricsVector<char> originalVector = Factory.createVector(new char[] { 'a', 'b', 'c', ..., 'z' });
// Create the generator by calling the appropriate method in the Factory class.
// Set the second parameter as 5, since we will generate 5-elemets permutations
Generator<char> gen = Factory.createPermutationWithRepetitionGenerator(originalVector, 5);
// Print the result
for (ICombinatoricsVector<char> perm : gen)
System.out.println( perm ); //combine the elements of perm into a single string and add to your queue
(警告:我没有测试以上内容)
编辑:我在思考这个问题时不得不查找组合和排列之间的区别 :) 我发现这个 link 作为一个简单的复习很有用:http://www.mathsisfun.com/combinatorics/combinations-permutations.html
这不是并行处理解决方案,而是优化得多的蛮力方法。您可以考虑将 Iterator 更改为 Spliterator。如果时间允许,我可能会在下面 post.
中给出一个 Spliterator 方法
package pwcracker;
import java.util.Iterator;
import java.util.Scanner;
public class pwcracker {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String pw;
int length;
System.out.println("Enter a password that is up to 5 chars and contains no numbers: ");
pw = "" + scan.nextLine();
length = pw.length();
SequentialPatternGenerator generator = new SequentialPatternGenerator(length);
generator.forEachRemaining(test -> {if(pw.equals(test)) {
System.out.println("Your password: " + test );
}});
}
}
class SequentialPatternGenerator implements Iterator<String> {
private static final char[] CHOICES = new char[]{'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
private static final int MAX_INDEX = CHOICES.length - 1;
private boolean keepProducing = true;
private final int[] indexes;
public SequentialPatternGenerator(final int length) {
indexes = new int[length];
initIndexes();
}
private void initIndexes() {
for (int i = 0; i < indexes.length; i++) {
indexes[i] = 0;
}
}
@Override
public boolean hasNext() {
if (!keepProducing) {
return false;
}
for (int i = 0; i < indexes.length; i++) {
if (indexes[i] < MAX_INDEX) {
return true;
}
}
return false;
}
@Override
public String next() {
if (!keepProducing || !hasNext()) {
return null;
}
String next = produceString();
adjustIndexes();
return next;
}
public void stop() {
keepProducing = false;
}
private String produceString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indexes.length; i++) {
sb.append(CHOICES[indexes[i]]);
}
return sb.toString();
}
private void adjustIndexes() {
int i;
for(i = 0 ; i < indexes.length ; i++) {
if(indexes[i] < MAX_INDEX) {
indexes[i] = indexes[i] + 1;
break;
}
}
for(int j=0; j < i; j++) {
indexes[j] = 0;
}
}
}
我为我的 11 年级计算机科学项目创建了一个程序,我制作了一个 java 密码破解器,可以暴力破解密码。但是,我想获得一些关于如何对我的 java 程序(下面提供的代码)进行多线程处理以加速暴力破解过程的建议。如果它有帮助的话,我是 运行 英特尔的 i7-3770 处理器,它是四核的,但每个内核有 2 个线程,所以一次有 8 个可能的线程。
代码如下:
import java.util.*;
import java.io.*;
class pwcracker
{
public static void main (String[] args)
{
Scanner scan = new Scanner( System.in );
Random rand = new Random();
Runtime.getRuntime().availableProcessors();
String pw, choices, guess;
long tries;
int j, length;
System.out.println("Enter a password that is up to 5 chars and contains no numbers: ");
pw = "" + scan.nextLine();
length = pw.length();
choices = "abcdefghijklmnopqrstuvwxyz";
tries = 0;
guess = "";
System.out.println("Your pw is: " + pw);
System.out.println("The length of your pw is: " + length);
System.out.println("for TEST- Guess: " + guess + "pw :"+pw);
if (guess != pw){
while (guess != pw)
{
j = 0;
guess = "";
while ( j < length )
{
guess = guess + choices.charAt( rand.nextInt ( choices.length() ) );
j = j + 1;
if (guess == pw)
{
System.out.println("Match found, ending loop..");
break;
}
}
System.out.println("2 Guess: " + guess + " pw :"+pw);
tries = tries + 1;
}
}
System.out.println("Here is your password: " + guess);
System.out.println("It took " + tries + " tries to guess it.");
}
}
首先,您想尽可能减少循环中不必要的函数调用。例如 choices.length 可以作为变量存储在内存中,比如 int choice = choice.length。这将优化您的程序,因为每次计算机不必计算长度时,它已经存储在内存中供其使用。
如果您想使用线程化路线,那么我会将其设置为 producer-consumer 算法。在高层,我们有生产者线程创建工作,我们有消费者线程执行工作,我们有一个共享队列对象,我们使用它来将工作单元从生产者转移到消费者。
在你的例子中,由于你的样本 space 相对较小(重复长度为 5 的排列),我将有一个生产者线程。如果您使用下面我的建议,这也将有助于使事情变得简单。 This tutorial 作为您的起点看起来很简单。至于要使用的线程总数,从小处着手,尝试使用不同数量的线程。
我看到您在随机创建字符串以进行检查。但是,由于这会产生大量重复和冗余的检查,因此我建议使用排列。也就是说,您需要长度为 5 的字母表字符的所有排列。我发现这个库可以 combinations and permutations。这将使您无需重复即可获得所有可能的安排。像这样:
// Create the initial vector of 26 elements (alphabet)
ICombinatoricsVector<char> originalVector = Factory.createVector(new char[] { 'a', 'b', 'c', ..., 'z' });
// Create the generator by calling the appropriate method in the Factory class.
// Set the second parameter as 5, since we will generate 5-elemets permutations
Generator<char> gen = Factory.createPermutationWithRepetitionGenerator(originalVector, 5);
// Print the result
for (ICombinatoricsVector<char> perm : gen)
System.out.println( perm ); //combine the elements of perm into a single string and add to your queue
(警告:我没有测试以上内容)
编辑:我在思考这个问题时不得不查找组合和排列之间的区别 :) 我发现这个 link 作为一个简单的复习很有用:http://www.mathsisfun.com/combinatorics/combinations-permutations.html
这不是并行处理解决方案,而是优化得多的蛮力方法。您可以考虑将 Iterator 更改为 Spliterator。如果时间允许,我可能会在下面 post.
中给出一个 Spliterator 方法package pwcracker;
import java.util.Iterator;
import java.util.Scanner;
public class pwcracker {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String pw;
int length;
System.out.println("Enter a password that is up to 5 chars and contains no numbers: ");
pw = "" + scan.nextLine();
length = pw.length();
SequentialPatternGenerator generator = new SequentialPatternGenerator(length);
generator.forEachRemaining(test -> {if(pw.equals(test)) {
System.out.println("Your password: " + test );
}});
}
}
class SequentialPatternGenerator implements Iterator<String> {
private static final char[] CHOICES = new char[]{'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
private static final int MAX_INDEX = CHOICES.length - 1;
private boolean keepProducing = true;
private final int[] indexes;
public SequentialPatternGenerator(final int length) {
indexes = new int[length];
initIndexes();
}
private void initIndexes() {
for (int i = 0; i < indexes.length; i++) {
indexes[i] = 0;
}
}
@Override
public boolean hasNext() {
if (!keepProducing) {
return false;
}
for (int i = 0; i < indexes.length; i++) {
if (indexes[i] < MAX_INDEX) {
return true;
}
}
return false;
}
@Override
public String next() {
if (!keepProducing || !hasNext()) {
return null;
}
String next = produceString();
adjustIndexes();
return next;
}
public void stop() {
keepProducing = false;
}
private String produceString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indexes.length; i++) {
sb.append(CHOICES[indexes[i]]);
}
return sb.toString();
}
private void adjustIndexes() {
int i;
for(i = 0 ; i < indexes.length ; i++) {
if(indexes[i] < MAX_INDEX) {
indexes[i] = indexes[i] + 1;
break;
}
}
for(int j=0; j < i; j++) {
indexes[j] = 0;
}
}
}