Mar-10-2017, 05:33 AM
i have this command originally written in C that i would like to rewrite in python 3. anyone want to join in? it takes a length as the only argument then outputs a candidate password randomly generated with letters, numbers, and special characters.
here is my original C code, untabified:
here is my original C code, untabified:
//----------------------------------------------------------------------------- // Copyright © 2012 - Phil D. Howard - All rights reserved // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. //----------------------------------------------------------------------------- // license ISC (BSD) //----------------------------------------------------------------------------- // author Philip Howard // email echo L3I2rF5kYaIvnz5ypHO0rz52rF5jLabX|rot13|mimencode -u|rot13 //----------------------------------------------------------------------------- // This file is best viewed using a fixed spaced font such as Courier and in a // display at least 144 columns wide. //----------------------------------------------------------------------------- // compile gcc -O3 -o mkpw mkpw.c && strip mkpw && ldd mkpw && ls -dl mkpw //----------------------------------------------------------------------------- #include <alloca.h> #include <errno.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define ARCHBITS 64 #define ARCHINT_T uint64_t #define DEFPWLEN 10 #define MAXPWLEN 32768 #define MINPWLEN 6 static unsigned long long limit = 5631351470947265625ULL; /* 75^10 */ // static unsigned long maxrn = 33554432; static unsigned long maxrn = 65536; static char rname[] = "/dev/urandom"; static char chset[75] = "%&+,-./0123456789:=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; static char class[75] = "000000011111111110000333333333333333333333333330222222222222222222222222220"; static int maxcount[4] = { MAXPWLEN, MAXPWLEN, MAXPWLEN, MAXPWLEN }; static int mincount[4] = { 1, 1, 1, 20 }; int main ( int argc, char ** argv ) { union { ARCHINT_T number ; unsigned char buffer [ARCHBITS/8]; } numbuf; FILE *rfile ; char *pw,*ptr,*pn,*pwend ; unsigned long cntrn ; int counts[4] ; int len,n,r ; unsigned char table [256]; //-- Get our own program name. pn = argv[0]; while ( * pn ) ++ pn; while ( pn > argv[0] && * pn != '/' ) -- pn; if ( * pn == '/' ) ++ pn; //-- Get desired password length. len = DEFPWLEN; if ( -- argc && * ++ argv ) { len = strtoul( * argv, NULL, 0 ); if ( len > MAXPWLEN ) len = MAXPWLEN; if ( len < MINPWLEN ) len = MINPWLEN; } //-- Open the random bit source. rfile = fopen( rname, "r" ); if ( ! rfile ) { fprintf( stderr, "%s: unable to open \"%s\" to read random bits: %s\n", pn, rname, strerror( errno ) ); return 1; } //-- Build character class lookup table. memset( table, 0, sizeof table ); for ( n = 0; n < 75; ++ n ) { table[ chset[n] ] = class[n] - '0'; } //-- Convert character class lookup to binary values. for ( ptr = class; * ptr; ++ ptr ) * ptr = * ptr - '0'; //-- Get automatic space sized for the requested length. pw = alloca( len + 1 ); if ( ! pw ) { fprintf( stderr, "%s: unable to allocate %llu bytes for password string\n", pn, (unsigned long long) ( len + 1 ) ); return 1; } pwend = pw + len; * pwend = 0; cntrn = 0; //-- Repeat until a password that meets requirements is generated. for (;;) { counts[0] = 0; counts[1] = 0; counts[2] = 0; counts[3] = 0; //-- Repeat until a password of sufficient length is generated. for ( ptr = pw; ptr < pwend; ) { //-- Check for max tries. if ( ++ cntrn > maxrn ) { fprintf( stderr, "%s: exceeded %lu random values without valid password\n", pn, maxrn ); return 1; } //-- Read random bits r = fread( numbuf.buffer, 1, ARCHBITS/8, rfile ); if ( feof( rfile ) ) { fprintf( stderr, "%s: unexpected EOF from \"%s\"\n", pn, rname ); fclose( rfile ); return 1; } if ( r < 8 ) { fprintf( stderr, "%s: error reading 8 bytes from \"%s\": %s\n", pn, rname, strerror( errno ) ); fclose( rfile ); return 1; } //-- Reject values that can lead to an uneven distribution of characters. if ( numbuf.number > limit ) continue; //-- Encode some characters. for ( n = 0; ptr < pwend && n < (ARCHBITS/6); ++ ptr, ++ n ) { r = numbuf.number % 75ULL; numbuf.number /= 75ULL; *ptr = chset[r]; counts[ table[ *ptr ] ]++; } } // printf( "%2u %2u %2u %2u %s\n", counts[0], counts[1], counts[2], counts[3], pw ); if ( counts[0] >= mincount[0] && counts[0] <= maxcount[0] && counts[1] >= mincount[1] && counts[1] <= maxcount[1] && counts[2] >= mincount[2] && counts[2] <= maxcount[2] && counts[3] >= mincount[3] && counts[3] <= maxcount[3] ) break; } fclose( rfile ); puts( pw ); return 0; }