Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #26441 > unrolled thread

random password generator

Started byPaul Rubin <no.email@nospam.invalid>
First post2013-10-12 19:07 -0700
Last post2013-10-13 14:43 -0700
Articles 11 — 4 participants

Back to article view | Back to comp.lang.forth


Contents

  random password generator Paul Rubin <no.email@nospam.invalid> - 2013-10-12 19:07 -0700
    Re: random password generator hughaguilar96@yahoo.com - 2013-10-12 22:01 -0700
    Re: random password generator Paul Rubin <no.email@nospam.invalid> - 2013-10-12 22:32 -0700
      Re: random password generator hughaguilar96@yahoo.com - 2013-10-12 22:44 -0700
    Re: random password generator "WJ" <w_a_x_man@yahoo.com> - 2013-10-13 08:23 +0000
      Re: random password generator Paul Rubin <no.email@nospam.invalid> - 2013-10-13 05:46 -0700
      Re: random password generator "WJ" <w_a_x_man@yahoo.com> - 2013-10-13 17:09 +0000
    Re: random password generator Bernd Paysan <bernd.paysan@gmx.de> - 2013-10-13 20:32 +0200
      Re: random password generator Paul Rubin <no.email@nospam.invalid> - 2013-10-13 12:27 -0700
        Re: random password generator Bernd Paysan <bernd.paysan@gmx.de> - 2013-10-13 22:52 +0200
          Re: random password generator Paul Rubin <no.email@nospam.invalid> - 2013-10-13 14:43 -0700

#26441 — random password generator

FromPaul Rubin <no.email@nospam.invalid>
Date2013-10-12 19:07 -0700
Subjectrandom password generator
Message-ID<7x38o5zzwz.fsf@ruckus.brouhaha.com>
#! /usr/bin/gforth
12 constant password_length
variable rfile
create buf 1 chars allot 

s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
( addr u ) assert( dup 64 = ) 2drop constant alphabet

: chk ( n -- )  assert( dup = ) drop ;
: tchar ( c -- ) $3f AND alphabet + c@ emit ;
: open-rand.1 ( -- wfileid ) s" /dev/urandom" r/o open-file 0 chk ;
: open-rand ( -- ) open-rand.1 rfile ! ;
: randombyte ( -- c ) buf 1 rfile @ read-file 0 chk 1 chk buf c@ ;
: run ( -- ) open-rand   password_length 0 do randombyte tchar loop cr ;

run bye

[toc] | [next] | [standalone]


#26445

Fromhughaguilar96@yahoo.com
Date2013-10-12 22:01 -0700
Message-ID<dbbb6ae5-89ce-408e-b2bf-7663458f39a5@googlegroups.com>
In reply to#26441
I glanced over your code. It is okay --- but it seems to have too many magic numbers in the code --- you could make it more robust in that it would allow you to change the alphabet without having to change the code.

This is similar to code I wrote a long time ago (in high-school) for shuffling a deck of cards.

[toc] | [prev] | [next] | [standalone]


#26447

FromPaul Rubin <no.email@nospam.invalid>
Date2013-10-12 22:32 -0700
Message-ID<7xr4bpivlh.fsf@ruckus.brouhaha.com>
In reply to#26441
Paul Rubin <no.email@nospam.invalid> writes:
> : chk ( n -- )  assert( dup = ) drop ;

That should say:

: chk ( n n -- ) assert( 2dup = ) 2drop ;

[toc] | [prev] | [next] | [standalone]


#26450

Fromhughaguilar96@yahoo.com
Date2013-10-12 22:44 -0700
Message-ID<04651631-6c46-47c8-9153-6730b6110b46@googlegroups.com>
In reply to#26447
On Saturday, October 12, 2013 10:32:58 PM UTC-7, Paul Rubin wrote:
> Paul Rubin <no.email@nospam.invalid> writes:
> > : chk ( n -- )  assert( dup = ) drop ;
> 
> That should say:
> 
> : chk ( n n -- ) assert( 2dup = ) 2drop ;

ASSERT( is non-standard --- I would just stick with ABORT" which is ANS-Forth, and gives you a meaningful error message.

Also, you shouldn't have all of this low-level error-checking code mixed in with your application code --- that belongs in a library, as it is essentially the same every time you work with files --- that is what I do in the novice package.

[toc] | [prev] | [next] | [standalone]


#26459

From"WJ" <w_a_x_man@yahoo.com>
Date2013-10-13 08:23 +0000
Message-ID<l3dla2$9vl$1@dont-email.me>
In reply to#26441
Paul Rubin wrote:

> #! /usr/bin/gforth
> 12 constant password_length
> variable rfile
> create buf 1 chars allot 
> 
> s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
> ( addr u ) assert( dup 64 = ) 2drop constant alphabet
> 
> : chk ( n -- )  assert( dup = ) drop ;
> : tchar ( c -- ) $3f AND alphabet + c@ emit ;
> : open-rand.1 ( -- wfileid ) s" /dev/urandom" r/o open-file 0 chk ;
> : open-rand ( -- ) open-rand.1 rfile ! ;
> : randombyte ( -- c ) buf 1 rfile @ read-file 0 chk 1 chk buf c@ ;
> : run ( -- ) open-rand   password_length 0 do randombyte tchar loop cr ;
> 
> run bye

Ruby:

P_len = 12

alphabet =
  [('a'..'z'),('A'..'Z'),('0'..'9'),'_'].map( &:to_a ).reduce( :+ )
srand
Array.new(P_len){ rand alphabet.size }.map{|n| alphabet[n,1] }.
  join
    ==>"Enu1U9_Mfz0c"

[toc] | [prev] | [next] | [standalone]


#26467

FromPaul Rubin <no.email@nospam.invalid>
Date2013-10-13 05:46 -0700
Message-ID<7x4n8lcp9s.fsf@ruckus.brouhaha.com>
In reply to#26459
"WJ" <w_a_x_man@yahoo.com> writes:
> srand

You have to use /dev/urandom which is a crypto RNG seeded by system
entropy.

[toc] | [prev] | [next] | [standalone]


#26475

From"WJ" <w_a_x_man@yahoo.com>
Date2013-10-13 17:09 +0000
Message-ID<l3ek44$bjb$1@dont-email.me>
In reply to#26459
WJ wrote:

> Paul Rubin wrote:
> 
> > #! /usr/bin/gforth
> > 12 constant password_length
> > variable rfile
> > create buf 1 chars allot 
> > 
> > s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
> > ( addr u ) assert( dup 64 = ) 2drop constant alphabet
> > 
> > : chk ( n -- )  assert( dup = ) drop ;
> > : tchar ( c -- ) $3f AND alphabet + c@ emit ;
> > : open-rand.1 ( -- wfileid ) s" /dev/urandom" r/o open-file 0 chk ;
> > : open-rand ( -- ) open-rand.1 rfile ! ;
> > : randombyte ( -- c ) buf 1 rfile @ read-file 0 chk 1 chk buf c@ ;
> > : run ( -- ) open-rand   password_length 0 do randombyte tchar loop cr ;
> > 
> > run bye
> 
> Ruby:
> 
> P_len = 12
> 
> alphabet =
>   [('a'..'z'),('A'..'Z'),('0'..'9'),'_'].map( &:to_a ).reduce( :+ )

alphabet = ['a'..'z','A'..'Z','0'..'9','_'].map( &:to_a ).flatten

> srand
> Array.new(P_len){ rand alphabet.size }.map{|n| alphabet[n,1] }.
>   join
>     ==>"Enu1U9_Mfz0c"

[toc] | [prev] | [next] | [standalone]


#26479

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-10-13 20:32 +0200
Message-ID<l3ep0h$43g$1@online.de>
In reply to#26441
Paul Rubin wrote:

> #! /usr/bin/gforth
> 12 constant password_length
> variable rfile
> create buf 1 chars allot
> 
> s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
> ( addr u ) assert( dup 64 = ) 2drop constant alphabet
> 
> : chk ( n -- )  assert( dup = ) drop ;
> : tchar ( c -- ) $3f AND alphabet + c@ emit ;
> : open-rand.1 ( -- wfileid ) s" /dev/urandom" r/o open-file 0 chk ;
> : open-rand ( -- ) open-rand.1 rfile ! ;
> : randombyte ( -- c ) buf 1 rfile @ read-file 0 chk 1 chk buf c@ ;
> : run ( -- ) open-rand   password_length 0 do randombyte tchar loop cr ;
> 
> run bye

This is a script.  Things you just need to do once (e.g. open /dev/random) 
don't need to go into a definition.  Just do them in interactive mode.  Use 
throw on iors.  If you have questions whether your alphabet really is 64 
characters, add a ~~ right after the string once for debugging.

Here's how I would do it:

#! /usr/bin/gforth

s" /dev/urandom" r/o open-file throw value rndfd
: randombyte ( -- c )  rndfd key-file ;
: >alphabet ( n -- c )  $3F and
  s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
  drop + c@ ;
: passwd ( len -- )  0 ?DO  randombyte >alphabet emit  LOOP cr ;

12 passwd bye

If you want to make that more robust for different alphabets (some passwords 
may have only digits and letters in it, or may not have uppercase letters to 
avoid confusion and whatever...), better do that:

#! /usr/bin/gforth

s" /dev/urandom" r/o open-file throw value rndfd
: randomword ( -- u16 ) rndfd key-file rndfd key-file 8 lshift + ;
: >alphabet ( u16 -- c )
  s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
  rot * 16 rshift + c@ ;
: passwd ( len -- )  0 ?DO  randomword >alphabet emit  LOOP cr ;

12 passwd bye

BTW: Test what you have written, word by word.  Your chk does not work, 
because "dup =" is always true.

There is a reason why my >alphabet does neither contain the emit: This 
allows you to write checks for the word.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#26480

FromPaul Rubin <no.email@nospam.invalid>
Date2013-10-13 12:27 -0700
Message-ID<7xbo2tc6pn.fsf@ruckus.brouhaha.com>
In reply to#26479
Bernd Paysan <bernd.paysan@gmx.de> writes:
> This is a script.  Things you just need to do once (e.g. open /dev/random) 
> don't need to go into a definition.  Just do them in interactive mode.

Thanks!  Hmm, ok, I thought it was easier to debug and test stuff by
putting all the code into definitions, though in a very simple script
like this it probably doesn't matter much.

> Use throw on iors.  

Thanks, that's useful.  I just found the info in the exceptions chapter
of the gforth manual.  That took a little searching because throw isn't
in the word index (maybe you could add it):

http://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Word-Index.html

> If you have questions whether your alphabet really is 64 characters,
> add a ~~ right after the string once for debugging.

Yeah the assert was kind of a built-in unit test.  I generally prefer to
leave things like that in programs if I don't mind the tiny bit of
bloat.  It's mostly to catch if I make a mistake in a later
modification, rather than to check that the code works in the first
place.

> Here's how I would do it:
>
> #! /usr/bin/gforth
>
> s" /dev/urandom" r/o open-file throw value rndfd
> : randombyte ( -- c )  rndfd key-file ;
> : >alphabet ( n -- c )  $3F and
>   s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
>   drop + c@ ;
> : passwd ( len -- )  0 ?DO  randombyte >alphabet emit  LOOP cr ;
>
> 12 passwd bye

That is nice!  I didn't know about key-file either.

> : >alphabet ( u16 -- c )
>   s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
>   rot * 16 rshift + c@ ;

Don't you mean

 : >alphabet ( u16 -- c )
   s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
   rot swap mod + c@ ;

I considered something like that but I figured that the 6-bit alphabet
(or even a 5-bit one) was more in the spirit of Forth minimalism.

I haven't seen any recent systems that don't allow mixed case passwords
but some obnoxious ones -require- the presence of both cases and digits
(that's why I used 6 bits instead of 5).  I decided that most passwords
from this script have that because of their length, and I could just run
the script several times if necessary.

> BTW: Test what you have written, word by word.  Your chk does not work, 
> because "dup =" is always true.

Yes, result of a last-minute refactoring :(.  I posted a correction.

[toc] | [prev] | [next] | [standalone]


#26482

FromBernd Paysan <bernd.paysan@gmx.de>
Date2013-10-13 22:52 +0200
Message-ID<l3f15p$ev2$1@online.de>
In reply to#26480
Paul Rubin wrote:

>> : >alphabet ( u16 -- c )
>>s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
>>rot * 16 rshift + c@ ;
> 
> Don't you mean
> 
> : >alphabet ( u16 -- c )
> s" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_="
> rot swap mod + c@ ;

No, I mean multiply and then divide (with a right shift in this case). u16 
is 0..ffff, and by dividing it is between [0..1[.  That gives a uniform 
distribution over all characters in the string, and is typically faster than 
a modulus.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

[toc] | [prev] | [next] | [standalone]


#26483

FromPaul Rubin <no.email@nospam.invalid>
Date2013-10-13 14:43 -0700
Message-ID<7xppr8u9r7.fsf@ruckus.brouhaha.com>
In reply to#26482
Bernd Paysan <bernd.paysan@gmx.de> writes:
>>>rot * 16 rshift + c@ ;

> No, I mean multiply and then divide (with a right shift in this
> case). u16 is 0..ffff, and by dividing it is between [0..1[.  That
> gives a uniform distribution over all characters in the string, and is
> typically faster than a modulus.

Aha, very clever, it was confusing at first because small examples end
up at 0.  Basically the lower bits of the u16 are mostly thrown away,
while modulus uses the lower bits and mostly throws away the upper ones.
It works out about the same in the end.  Both methods are slightly
non-uniform unless the alphabet size exactly divides 2**16, but that's
fine for this purpose (the effect on the output distribution's entropy
is almost zero).  Thanks again.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.forth


csiph-web