/** * Dictionary generator/compressor for PPM (Password Probability Matrix). * * Creates and compresses (lossily) hashes for time-space tradeoff * brute-forcing. PoC only. * * http://2600hacker.stores.yahoo.net/pasprobmat.html **/ import java.security.NoSuchAlgorithmException; import java.math.BigInteger; import java.util.BitSet; import java.io.*; public class PPMGen { private static byte MIN_CHAR = 32; private static byte MAX_CHAR = 126; private static int HASH_SIZE = 16*8192; private static int CTMASK = 0x0001FFFF; // 17 bits private static BitSet [] ppm; static { ppm = new BitSet[ 95*95 ]; for( int i = 0; i < ppm.length; i++ ) { ppm[ i ] = new BitSet( HASH_SIZE ); } } private static byte [] genHash( String password ) throws NoSuchAlgorithmException { return OneWayHash.hash( password ).getBytes(); } private static int getIndex( byte c1, byte c2 ) { return ( c1 - MIN_CHAR )*95 + ( c2 - MIN_CHAR ); } private static int computeCTIndex( byte [] b ) { int ret = byteArrayToInt( b, 0 ); return ret & CTMASK; } private static int byteArrayToInt(byte[] b, int offset) { int value = 0; for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (b[i + offset] & 0x000000FF) << shift; } return value; } public static void main( String [] args ) { try { byte [] plain = new byte[ 4 ]; for( plain[ 0 ] = MIN_CHAR; plain[ 0 ] <= MAX_CHAR; plain[ 0 ]++ ) { System.out.print( "." ); for( plain[ 1 ] = MIN_CHAR; plain[ 1 ] <= MAX_CHAR; plain[ 1 ]++ ) { for( plain[ 2 ] = MIN_CHAR; plain[ 2 ] <= MAX_CHAR; plain[ 2 ]++ ) { for( plain[ 3 ] = MIN_CHAR; plain[ 3 ] <= MAX_CHAR; plain[ 3 ]++ ) { int ptIndex = getIndex( plain[ 0 ], plain[ 1 ] ); int ctIndex = computeCTIndex( genHash( new String( plain ) ) ); ppm[ ptIndex ].set( ctIndex ); } } } } System.out.println( "\n[+] Done." ); FileOutputStream fos = new FileOutputStream( "4char.ppm" ); ObjectOutputStream oos = new ObjectOutputStream( fos ); oos.writeObject( ppm ); oos.close(); } catch( Exception e ) { e.printStackTrace(); } } }