Keyspace List for WPA on Default Routers
#71
If I'm not totally (I mean completely!!!) mistaken you are totally looking at the wrong code.

The code posted by mrfancypants here: https://repl.it/JMbi/4
is not (just) the key generator.

This is a special code (specifically coded for a single check/situation) that was answering this post https://hashcat.net/forum/thread-6170-po...l#pid35744 , e.g. to check if the pwgen () function can generate the correct password candidate if the first 8 letters are known (
mrfancypants even mentioned this here https://hashcat.net/forum/thread-6170-po...l#pid35743).

That means, your code does not need the pw_to_candidate_ints () function.
Instead, it just needs a loop of all x values from 0 to 0x7FFFFFFF as an input for the pwgen(x) function.

This actually should be very obvious.
... and the amount of memory needed (without the search for a specific known and truncated 8 letter password candidate, which was just a test!!!) will be very low (less than 1 KB for sure, it just does some mathematical computation and has a static string pw_charset).

That said, the whole discussion about is return (y for y in cands if pwgen(y)[:l]==x) better than return [y for y in cands if pwgen(y)[:l]==x] makes no sense, because a password generator does not need pw_to_candidate_ints () at all.

pw_to_candidate_ints () could probably also be replaced by just an external "grep"-like filter (that would have probably avoided this funny confusion, but it probably would have needed to call pwgen () way more often, therefore the decision to implement a search function like pw_to_candidate_ints () makes sense, but just to proof that a specific 8-letter-truncated password candidate is within the whole password candidate list).


update: I attach here some example code such that you can get an idea of what *I think* is the actual password generator code:

python code (file: nvg599.py):
Code:
#!/usr/bin/env python

# author: philsmd
# date: July 2017
# license: public domain
# full credits go to mrfancypants for the actual/original contribution

# to check if a password candidate is within the set:
# python nvg599.py | grep '^b=+#gc5q'

pw_charset = 'abcdefghijkmnpqrstuvwxyz23456789#%+=?'

# helper function (the actual password generator):

def pwgen (x):
  x *= 2 ** 32 + 2
  x  = int (float (x))

  pw = ''

  for n in range (0, 12):
    rem  = x

    rem %= 37
    x   /= 37

    pw = pw_charset[rem] + pw

  return pw


# start:

x = 0

while x <= 0x7fffffff:
  print pwgen (x)
  x += 1

little optimized version, ANSI C with custom file I/O buffering (file: nvg599.c):
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

/*
* author: philsmd
* date: July 2017
* license: public domain
* full credits go to mrfancypants for the actual/original contribution
*/

typedef uint8_t  u8;
typedef uint32_t u32;
typedef uint64_t u64;

const static u8 PW_CHARSET[] = "abcdefghijkmnpqrstuvwxyz23456789#%+=?";

#define PW_LENGTH   12
#define LINE_LENGTH (PW_LENGTH + 1)

#define OUTBUFSZ    BUFSIZ
#define EXTRA_BYTES 0x100

#if !defined MIN
  #define MIN(x,y) (((u32) x < (u32) y) ? (u32) x : (u32) y)
#endif

int main ()
{
  /*
   * Initialize output file and I/O buffering
   */

  #ifdef WINDOWS
  setmode (fileno (stdout), O_BINARY);
  setmode (fileno (stderr), O_BINARY);
  #endif

  FILE *fp_out = stdout;

  setbuf (fp_out, NULL);

  /*
   * Initialize output buffer
   */

  u8 buf[OUTBUFSZ + EXTRA_BYTES];

  u32 cur_buffer_len = 0;

  /*
   * Initialize password buffer
   */

  u8 pw[LINE_LENGTH] = { 0 };

  pw[PW_LENGTH] = '\n'; // new lines are needed too

  /*
   * start
   */

  for (u64 i = 0; i <= 0x7fffffff; i++)
  {
    u64 x = (double) (i * ((1l << 32) + 2));

    for (int n = PW_LENGTH - 1; n >= 0; n--, x /= 37)
    {
      pw[n] = PW_CHARSET[x % 37];
    }


    // copy the password (pw) to the output buffer:

    u32 copy_size = MIN (LINE_LENGTH, OUTBUFSZ - cur_buffer_len);

    memcpy (buf + cur_buffer_len, pw, copy_size);

    cur_buffer_len += copy_size;

    if (cur_buffer_len < OUTBUFSZ) continue;


    // buffer is full, write to the output file:

    fwrite (buf, 1, OUTBUFSZ, fp_out);


    // reset buffer length and copy the remaining bytes:

    cur_buffer_len = LINE_LENGTH - copy_size;

    memcpy (buf, pw + copy_size, cur_buffer_len);
  }


  // we must guarantee that we also write the final buffer to the file:

  fwrite (buf, 1, cur_buffer_len, fp_out);


  // close the file:

  fclose (fp_out);

  return 0;
}

(please do not blame me for the code, I can also not guarantee that it doesn't contain bugs, but hopefully there won't be any bugs in this small code)
Reply


Messages In This Thread
RE: Keyspace List for WPA on Default Routers - by philsmd - 07-16-2017, 09:11 PM