refcodes-generator: Mass produce password permutations and distinct IDs

README

The REFCODES.ORG codes represent a group of artifacts consolidating parts of my work in the past years. Several topics are covered which I consider useful for you, programmers, developers and software engineers.

What is this repository for?

This artifact provides word morphs mass production functionality for generating arbitrary distinct IDs similar to UUIDs (as of the UniqueIdGenerator type) or for generating permutations of words with a given alphabet and permutation rules (as of the AlphabetCounter alongside the AlphabetCounterComposite types) as well as multi threading concurrency support (as of the ConcurrentBufferedGeneratorDecorator and ThreadLocalBufferedGeneratorDecorator types) for such Generator (Iterator) types.

Please keep in mind that the permutation functionality introduced below is intended for personal data recovery and educational use only! Please respect the privacy of your fellow people!

How do I get set up?

To get up and running, include the following dependency (without the three dots “…”) in your pom.xml:

1
2
3
4
5
6
7
8
9
<dependencies>
	...
	<dependency>
		<artifactId>refcodes-generator</artifactId>
		<groupId>org.refcodes</groupId>
		<version>3.3.5</version>
	</dependency>
	...
</dependencies>

The artifact is hosted directly at Maven Central. Jump straight to the source codes at Bitbucket. Read the artifact’s javadoc at javadoc.io.

Snippets of interest

Below find some code snippets which demonstrate the various aspects of using the refcodes-generator artifact (and , if applicable, its offsprings). See also the example source codes of this artifact for further information on the usage of this artifact.

Tailor-made password permutations

Tailor-made password permutations use expressions to define permutations aspects and chaining of multiple such defined permutations together to produce custom password ranges.

The code snippet below will produce all permutations ranging from Secret till secret999password???:

1
2
3
4
5
6
7
8
9
10
11
12
import org.refcodes.generator.AlphabetCounterComposite;
...
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( 
		"('Secret','secret')", 				// 1st part of the password
		"[0-3]:{0-9}",								// 2nd part of the password
		"('','Password','password')",	// 3rd part of the password
		"[0-3]:{!,?}"									// 4th part of the password
	);
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
...

Note that the daisy chained expressions ('Secret','secret'), [0-3]:{0-9}, ('','Password','password'), and "[0-3]:{!,?} combined are responsible for the last secret999password??? password’s portions secret, 999, password and ??? (in that order) and produce 99990 password variants!

Secret
Secret!
Secret?
...
secret999password?!?
secret999password??!
secret999password???

The code snippet below will produce all permutations ranging from A000 till ZZZ999 (this may take a while):

1
2
3
4
5
6
7
8
9
10
import org.refcodes.generator.AlphabetCounterComposite;
...
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite(
		"[1-3]:{A-Z}",								// 1st part of the password
		"[3-3]:{0-9}"									// 2nd part of the password
	);
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
...

Note that the daisy chained expressions [1-3]:{A-Z} and [3-3]:{0-9} combined are responsible for the last ZZZ999 password’s portions ZZZ and 999 (in that order) and produce 18278000 password variants!

A000
A001
A002
...
ZZZ997
ZZZ998
ZZZ999

Daisy chaining multiple expressions enables you to create arbitrary complex custom password counters.

Producing permutations from character sets

The code snippet below will produce all permutations with lengths between 2 and 4 for the letters a, b, c, d, e, f ranging from aa till ffff:

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounter;
...
	AlphabetCounter theCounter = new AlphabetCounter( 2, 4, 'a', 'b', 'c', 'd', 'e', 'f' );
	System.out.println( theCounter.toAlphabetExpression() );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
	System.out.println( theCounter.toAlphabetExpression() );
...

Note that the below output’s first [2-4]:{a,b,c,d,e,f}:"aa" and last [2-4]:{a,b,c,d,e,f}:"ffff" lines are not part of the counter’s permutations though represent expressions defining the counter’s initial and final state!

[2-4]:{a,b,c,d,e,f}:"aa"
aa
ab
ac
...
fffd
fffe
ffff
[2-4]:{a,b,c,d,e,f}:"ffff"

The code snippet below will produce all permutations with lengths between 2 and 4 for all hexadecimal digits ranging from 00 till FFFF (as of the CharSet definition):

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounter;
...
	AlphabetCounter theCounter = new AlphabetCounter( 2, 4, CharSet.HEXADECIMAL );
	System.out.println( theCounter.toAlphabetExpression() );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
	System.out.println( theCounter.toAlphabetExpression() );
...

Note that the below output’s first [2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"00" and last [2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"FFFF" lines are not part of the counter’s permutations though represent expressions defining the counter’s initial and final state!

[2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"00"
00
01
02
...
FFFD
FFFE
FFFF
[2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"FFFF"

Counting through word lists

The code snippet below will produce all the elements this, is, my, word, list, to, iterate, through:

1
2
3
4
5
6
7
8
9
10
11
import org.refcodes.generator.AlphabetCounter;
...
	AlphabetCounter theCounter = new AlphabetCounter( 
		new String[] { "this", "is", "my", "word", "list", "to", "iterate", "through" }
	);
	System.out.println( theCounter.toAlphabetExpression() );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
	System.out.println( theCounter.toAlphabetExpression() );
...

Note that the below output’s first ("this","is","my","word","list","to","iterate","through"):"this" and last ("this","is","my","word","list","to","iterate","through"):"through" lines are not part of the counter’s permutations though represent expressions defining the counter’s initial and final state!

("this","is","my","word","list","to","iterate","through"):"this"
this
is
my
word
list
to
iterate
through
("this","is","my","word","list","to","iterate","through"):"through"

Producing permutations from expressions

Using the expression [2-4]:{a,b,c,d,e,f}:'ce' the code snippet below will produce all permutations with lengths between 2 and 4 for the letters a, b, c, d, e, f ranging from ce till ffff:

Please keep in mind that expressions are like a shy fairies: Spaces not useful in definition are rejected with disapproval!

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounter;
...
	AlphabetCounter theCounter = new AlphabetCounter( "[2-4]:{a,b,c,d,e,f}:'ce'" );
	System.out.println( theCounter.toAlphabetExpression() );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
	System.out.println( theCounter.toAlphabetExpression() );
...

Note that the below output’s first [2-4]:{a,b,c,d,e,f}:"ce" and last [2-4]:{a,b,c,d,e,f}:"ffff" lines are not part of the counter’s permutations though represent expressions defining the counter’s initial and final state!

[2-4]:{a,b,c,d,e,f}:"ce"
ce
cf
da
...
fffd
fffe
ffff
[2-4]:{a,b,c,d,e,f}:"ffff"

Calling reset() on the above counter will make it start from aa again; This is important when daisy chaining counters behind each other to produce the full set of permutations of all counters combined and still be able to resume from a given counter’s state (see AlphabetCounterDecorator class).

Using the expression [2-4]:{HEXADECIMAL}:'CE' the code snippet below will produce all permutations with lengths between 2 and 4 for all hexadecimal digits ranging from CE till FFFF (as of the CharSet definition):

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounter;
...
	AlphabetCounter theCounter = new AlphabetCounter( "[2-4]:{HEXADECIMAL}:'CE'" );
	System.out.println( theCounter.toAlphabetExpression() );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
	System.out.println( theCounter.toAlphabetExpression() );
...

Note that the below output’s first [2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"CE"" and last [2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"FFFF" lines are not part of the counter’s permutations though represent expressions defining the counter’s initial and final state!

[2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"CE"
CE
CF
D0
...
FFFD
FFFE
FFFF
[2-4]:{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}:"FFFF"

Calling reset() on the above counter will make it start from 00 again; This is important when daisy chaining counters behind each other to produce the full set of permutations of all counters combined and still be able to resume from a given counter’s state (see AlphabetCounterComposite class).

Daisy chaining counters to produce complex passwords

The code snippet below will produce all permutations ranging from A000 till ZZZ999 (this may take a while):

1
2
3
4
5
6
7
8
9
10
import org.refcodes.generator.AlphabetCounterComposite;
...
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( 
		"[1-3]:{A-Z}",								// 1st part of the password
		"[3-3]:{0-9}"									// 2nd part of the password
	);
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
...

Note that the daisy chained expressions [1-3]:{A-Z} and [3-3]:{0-9} are responsible for the first A000 password’s portions A and 000 (in that order) and combined produce 18278000 password variants!

A000
A001
A002
...
ZZZ997
ZZZ998
ZZZ999

Alternate ways of declaring such a counter are as follows, producing the same result as the example above:

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounterComposite;
...
	AlphabetCounter theCounter1 = new AlphabetCounter( "[1-3]:{A-Z}" );
	AlphabetCounter theCounter2 = new AlphabetCounter( "[3-3]:{0-9}" );
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( theCounter1, theCounter2 );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
...

Note that the above code snippet still uses expressions [1-3]:{A-Z} as well as [3-3]:{0-9} to define the counters!

1
2
3
4
5
6
7
8
9
import org.refcodes.generator.AlphabetCounterComposite;
...
	AlphabetCounter theCounter1 = new AlphabetCounter( 1, 3, CharSet.UPPER_CASE );
	AlphabetCounter theCounter2 = new AlphabetCounter( 3, 3, CharSet.DECIMAL );
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( theCounter1, theCounter2 );
	while ( theCounter.hasNext() ) {
		System.out.println( theCounter.next() );
	}
...

Note that the above code snippet defines the counters programmatically without the need to declare expressions!

Generating arbitrary distinct IDs

The code snippet below produces 1000 distinct IDs (you may produce as many as fast as you want):

1
2
3
4
5
6
import org.refcodes.generator.UniqueIdGeneratorSingleton;
...
	for ( int i = 0; i < 1000; i++ ) {
		System.out.println( UniqueIdGeneratorSingleton.getInstance().next() );
	}
...

Note that a singleton is used with a predefined length of 36 with the IDs being BASE-64 URL alike encoded (padding chars are omitted)!

AY4NrboAAABgRUoNS4AAAAAAAAAAA0000000
AY4NrbsAAABgRUoNS8AAAAAAAAAAE0000000
AY4NrbwAAABgRUoNTAAAAAAAAAAAI0000000
...
AY4NsZ8AAABgRUoNUUAAAAAAAAA-U0000000
AY4NsaAAAABgRUoNUUAAAAAAAAA-Y0000000
AY4NsaEAAABgRUoNUUAAAAAAAAA-c0000000
...

The code snippet below also produces 1000 distinct IDs (you may produce as many as fast as you want):

1
2
3
4
5
6
7
import org.refcodes.generator.UniqueIdGenerator;
...
	UniqueIdGenerator theGenerator = new UniqueIdGenerator( 16 );
	for ( int i = 0; i < 1000; i++ ) {
		System.out.println( theGenerator.next() );
	}
...

Note that a length of 16 is used with the IDs being BASE-64 URL alike encoded (padding chars are omitted)!

AY4DatMABgRUqGKk
AY4DatQABgRUqGKo
AY4DatUABgRUqGKs
...
AY4DbrgABgRUqGL8
AY4DbrkABgRUqGL8
AY4DbroABgRUqGL8
...

Multi threading concurrency and buffered generators

The code snippet below uses a ConcurrentBufferedGeneratorDecorator to encapsulate a Generator instance for concurrent (multi threaded) access with a minimum of blocking as of synchronization issues (e.g. the AlphabetCounter and the AlphabetCounterComposite avoid synchronization as far as possible causing issues with the internal state when directly been accessed from multiple threads).

1
2
3
4
5
6
7
8
9
10
11
import org.refcodes.generator.AlphabetCounterComposite;
import org.refcodes.generator.ConcurrentBufferedGeneratorDecorator;
...
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( "'HelloWorld'", "[0-32]:{0-9,A-Z,a-z}" );
	BufferedGenerator<String> theGenerator = new ConcurrentBufferedGeneratorDecorator<>( theCounter );
	int index = 0;
	while ( theGenerator.hasNext() && index < 1000 ) {
		System.out.println( theGenerator.next() );
		index++;
	}
...

Note that the ConcurrentBufferedGeneratorDecorator internally uses a separate thread to fill up a BlockingQueue which makes it safe to be used in a multi threaded environment though does not completely eliminates delays as of synchronization issues!

HelloWorld
HelloWorld0
HelloWorld1
...

You may also use Iterator instances with the ConcurrentBufferedGeneratorDecorator type!

The code snippet below uses a ThreadLocalBufferedGeneratorDecorator to encapsulate a Generator instance for concurrent (multi threaded) access with a minimum of blocking as of synchronization issues (e.g. the AlphabetCounter and the AlphabetCounterComposite avoid synchronization as far as possible causing issues with the internal state when directly been accessed from multiple threads).

1
2
3
4
5
6
7
8
9
10
11
import org.refcodes.generator.AlphabetCounterComposite;
import org.refcodes.generator.ThreadLocalBufferedGeneratorDecorator;
...
	AlphabetCounterComposite theCounter = new AlphabetCounterComposite( "'HelloWorld'", "[0-32]:{0-9,A-Z,a-z}" );
	BufferedGenerator<String> theGenerator = new ThreadLocalBufferedGeneratorDecorator<>( theCounter );
	int index = 0;
	while ( theGenerator.hasNext() && index < 1000 ) {
		System.out.println( theGenerator.next() );
		index++;
	}
...

Note that the CRACKZIP application seems to benefit much more from the ThreadLocalBufferedGeneratorDecorator as from the ConcurrentBufferedGeneratorDecorator even though it does not use a separate thread though instead uses ThreadLocal buffers filled up by the according threads themselves.

HelloWorld
HelloWorld0
HelloWorld1
...

You may also use Iterator instances with the ThreadLocalBufferedGeneratorDecorator type!

Examples

See the CRACKZIP applications’ source code, the PASSGEN applications’ source code as well as the example source codes of this artifact for further information on the usage of this artifact.

Contribution guidelines

  • Report issues
  • Finding bugs
  • Helping fixing bugs
  • Making code and documentation better
  • Enhance the code

Who do I talk to?

  • Siegfried Steiner (steiner@refcodes.org)

Terms and conditions

The REFCODES.ORG group of artifacts is published under some open source licenses; covered by the refcodes-licensing (org.refcodes group) artifact - evident in each artifact in question as of the pom.xml dependency included in such artifact.