Eamorr
Eamorr

Reputation: 10012

Brute force my gpg password

Stupidly, I've forgotten my gpg password.

I know the password is made up of three of six strings connected by a "_".

The possibilites are (let's say) "1", "2", "3", "4", "5" and "6".

Let's say the password is actually "2_5_3".

How to loop through all combinations? There should be no duplicates (i.e. "2_2_4" is not a valid password)!

I'm trying to write this in Perl, but don't really know where to start. Pseudo-code is good.

Many thanks in advance,

UPDATE: OK, I got it working now.

Not as elegant as some of the solutions below...

#!/usr/bin/perl

use strict;
use warnings;

my @possibilities=("111","222","333","444","555","666","777");

my $size=scalar(@possibilities);
print $size."\n";

for(my $i=0;$i<$size;$i++){
        for(my $j=0;$j<$size;$j++){
                for(my $k=0;$k<$size;$k++){
                        if($i==$j || $j==$k || $i==$k){

                        }else{
                                print $i."_".$j."_".$k."\n";
                        }
                }
        }
}

Upvotes: 1

Views: 1148

Answers (3)

Lukasz Siemiradzki
Lukasz Siemiradzki

Reputation: 336

There is a module for that - Algorithm::Combinatorics.

Upvotes: 1

Zeta
Zeta

Reputation: 105905

Basically you need three for loops to iterate over each word (or a multi-index). Since you want to ensure that there aren't any duplicates you have to skip those (Python code):

names = ["abc","def","ghi","jkl","mno","pqr"]

for x in names:
    for y in names:
        if y in [x]: # word already used?
            continue # skip duplicates
        for z in names:
            if z in [x,y]: # word already used?
                continue   # skip duplicates
            print(x+"_"+y+"_"+z)

UPDATE: Perl code (the very first I've ever written, so I guess it's gross for the Perl developer's eye...)

use strict;
use warnings;

my @words = ("abc","def","ghi","jkl","mno","pqr");
foreach my $w1 (@words){
    foreach my $w2(@words){
        next if $w1 eq $w2;
        foreach my $w3(@words){
        next if $w3 eq $w1;
        next if $w3 eq $w2;
            print $w1.'_'.$w2.'_'.$w3."\n";
        }
    }
}

Upvotes: 3

Toto
Toto

Reputation: 91488

Here a way to do it with perl:

my @l = glob "{1,2,3,4,5,6}_{1,2,3,4,5,6}_{1,2,3,4,5,6}";
@l = grep{!/(\d)[_\d]*\1/}@l;

Upvotes: 10

Related Questions